blob: da313f7bb549e48c784483e63b6fe8cd04b46b42 [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
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05008from gc import collect, get_referrers
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02009from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE, ESHUTDOWN
Hynek Schlawackf8979a52015-09-05 21:25:25 +020010from sys import platform, getfilesystemencoding, version_info
Maximilian Hils1d95dea2015-08-17 19:27:20 +020011from socket import MSG_PEEK, SHUT_RDWR, error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040012from os import makedirs
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040013from os.path import join
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -040014from unittest import main
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040015from weakref import ref
Abraham Martinef063482015-03-25 14:06:24 +000016from warnings import catch_warnings, simplefilter
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050017
Hynek Schlawack734d3022015-09-05 19:19:32 +020018import pytest
19
Hynek Schlawackf90e3682016-03-11 11:21:13 +010020from six import PY3, text_type
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050021
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040022from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080023from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040024from OpenSSL.crypto import dump_privatekey, load_privatekey
25from OpenSSL.crypto import dump_certificate, load_certificate
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040026from OpenSSL.crypto import get_elliptic_curves
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040027
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040028from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
29from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040030from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040031from OpenSSL.SSL import (
32 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
33 TLSv1_1_METHOD, TLSv1_2_METHOD)
34from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040035from OpenSSL.SSL import (
36 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040037
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040038from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050039 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
40 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
41 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
42
43from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070044 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050045from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070046 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040047
Cory Benfieldba1820d2015-04-13 17:39:12 -040048from OpenSSL._util import lib as _lib
49
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050050try:
51 from OpenSSL.SSL import OP_NO_QUERY_MTU
52except ImportError:
53 OP_NO_QUERY_MTU = None
54try:
55 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
56except ImportError:
57 OP_COOKIE_EXCHANGE = None
58try:
59 from OpenSSL.SSL import OP_NO_TICKET
60except ImportError:
61 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040062
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040063try:
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -040064 from OpenSSL.SSL import OP_NO_COMPRESSION
65except ImportError:
66 OP_NO_COMPRESSION = None
67
68try:
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040069 from OpenSSL.SSL import MODE_RELEASE_BUFFERS
70except ImportError:
71 MODE_RELEASE_BUFFERS = None
72
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040073try:
74 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
75except ImportError:
76 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
77
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040078from OpenSSL.SSL import (
79 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
80 SSL_ST_OK, SSL_ST_RENEGOTIATE,
81 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
82 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
83 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
84 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040085
Hynek Schlawackf0e66852015-10-16 20:18:38 +020086from .util import WARNING_TYPE_EXPECTED, NON_ASCII, TestCase, b
87from .test_crypto import (
88 cleartextCertificatePEM, cleartextPrivateKeyPEM,
89 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
90 root_cert_pem)
91
Hynek Schlawackde00dd52015-09-05 19:09:26 +020092
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040093# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
94# to use)
95dhparam = """\
96-----BEGIN DH PARAMETERS-----
97MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
98-----END DH PARAMETERS-----
99"""
100
101
Hynek Schlawackb4f02402015-09-05 20:48:34 +0200102skip_if_py3 = pytest.mark.skipif(PY3, reason="Python 2 only")
Hynek Schlawackf8979a52015-09-05 21:25:25 +0200103skip_if_py26 = pytest.mark.skipif(
104 version_info[0:2] == (2, 6),
105 reason="Python 2.7 and later only"
106)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200107
108
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400109def join_bytes_or_unicode(prefix, suffix):
110 """
111 Join two path components of either ``bytes`` or ``unicode``.
112
113 The return type is the same as the type of ``prefix``.
114 """
115 # If the types are the same, nothing special is necessary.
116 if type(prefix) == type(suffix):
117 return join(prefix, suffix)
118
119 # Otherwise, coerce suffix to the type of prefix.
120 if isinstance(prefix, text_type):
121 return join(prefix, suffix.decode(getfilesystemencoding()))
122 else:
123 return join(prefix, suffix.encode(getfilesystemencoding()))
124
125
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400126def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400127 return ok
128
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400129
Rick Deanb1ccd562009-07-09 23:52:39 -0500130def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400131 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400132 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400133 """
134 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500135 port = socket()
136 port.bind(('', 0))
137 port.listen(1)
138 client = socket()
139 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400140 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400141 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500142 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500143
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400144 # Let's pass some unencrypted data to make sure our socket connection is
145 # fine. Just one byte, so we don't have to worry about buffers getting
146 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400147 server.send(b("x"))
148 assert client.recv(1024) == b("x")
149 client.send(b("y"))
150 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500151
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400152 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400153 server.setblocking(False)
154 client.setblocking(False)
Jim Shaver46f28912015-05-29 19:32:16 -0400155
Rick Deanb1ccd562009-07-09 23:52:39 -0500156 return (server, client)
157
158
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400159def handshake(client, server):
160 conns = [client, server]
161 while conns:
162 for conn in conns:
163 try:
164 conn.do_handshake()
165 except WantReadError:
166 pass
167 else:
168 conns.remove(conn)
169
170
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400171def _create_certificate_chain():
172 """
173 Construct and return a chain of certificates.
174
175 1. A new self-signed certificate authority certificate (cacert)
176 2. A new intermediate certificate signed by cacert (icert)
177 3. A new server certificate signed by icert (scert)
178 """
179 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
180
181 # Step 1
182 cakey = PKey()
183 cakey.generate_key(TYPE_RSA, 512)
184 cacert = X509()
185 cacert.get_subject().commonName = "Authority Certificate"
186 cacert.set_issuer(cacert.get_subject())
187 cacert.set_pubkey(cakey)
188 cacert.set_notBefore(b("20000101000000Z"))
189 cacert.set_notAfter(b("20200101000000Z"))
190 cacert.add_extensions([caext])
191 cacert.set_serial_number(0)
192 cacert.sign(cakey, "sha1")
193
194 # Step 2
195 ikey = PKey()
196 ikey.generate_key(TYPE_RSA, 512)
197 icert = X509()
198 icert.get_subject().commonName = "Intermediate Certificate"
199 icert.set_issuer(cacert.get_subject())
200 icert.set_pubkey(ikey)
201 icert.set_notBefore(b("20000101000000Z"))
202 icert.set_notAfter(b("20200101000000Z"))
203 icert.add_extensions([caext])
204 icert.set_serial_number(0)
205 icert.sign(cakey, "sha1")
206
207 # Step 3
208 skey = PKey()
209 skey.generate_key(TYPE_RSA, 512)
210 scert = X509()
211 scert.get_subject().commonName = "Server Certificate"
212 scert.set_issuer(icert.get_subject())
213 scert.set_pubkey(skey)
214 scert.set_notBefore(b("20000101000000Z"))
215 scert.set_notAfter(b("20200101000000Z"))
216 scert.add_extensions([
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200217 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400218 scert.set_serial_number(0)
219 scert.sign(ikey, "sha1")
220
221 return [(cakey, cacert), (ikey, icert), (skey, scert)]
222
223
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400224class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400225 """
226 Helper mixin which defines methods for creating a connected socket pair and
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200227 for forcing two connected SSL sockets to talk to each other via memory
228 BIOs.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400229 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500230 def _loopbackClientFactory(self, socket):
231 client = Connection(Context(TLSv1_METHOD), socket)
232 client.set_connect_state()
233 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400234
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500235 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400236 ctx = Context(TLSv1_METHOD)
237 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
238 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500239 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400240 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500241 return server
242
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500243 def _loopback(self, serverFactory=None, clientFactory=None):
244 if serverFactory is None:
245 serverFactory = self._loopbackServerFactory
246 if clientFactory is None:
247 clientFactory = self._loopbackClientFactory
248
249 (server, client) = socket_pair()
250 server = serverFactory(server)
251 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400252
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400253 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400254
255 server.setblocking(True)
256 client.setblocking(True)
257 return server, client
258
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400259 def _interactInMemory(self, client_conn, server_conn):
260 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900261 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400262 objects. Copy bytes back and forth between their send/receive buffers
263 for as long as there is anything to copy. When there is nothing more
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200264 to copy, return :py:obj:`None`. If one of them actually manages to
265 deliver some application bytes, return a two-tuple of the connection
266 from which the bytes were read and the bytes themselves.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400267 """
268 wrote = True
269 while wrote:
270 # Loop until neither side has anything to say
271 wrote = False
272
273 # Copy stuff from each side's send buffer to the other side's
274 # receive buffer.
275 for (read, write) in [(client_conn, server_conn),
276 (server_conn, client_conn)]:
277
278 # Give the side a chance to generate some more bytes, or
279 # succeed.
280 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400281 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400282 except WantReadError:
283 # It didn't succeed, so we'll hope it generated some
284 # output.
285 pass
286 else:
287 # It did succeed, so we'll stop now and let the caller deal
288 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400289 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400290
291 while True:
292 # Keep copying as long as there's more stuff there.
293 try:
294 dirty = read.bio_read(4096)
295 except WantReadError:
296 # Okay, nothing more waiting to be sent. Stop
297 # processing this send buffer.
298 break
299 else:
300 # Keep track of the fact that someone generated some
301 # output.
302 wrote = True
303 write.bio_write(dirty)
304
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400305 def _handshakeInMemory(self, client_conn, server_conn):
Jean-Paul Calderoneb2b40782014-05-06 08:47:40 -0400306 """
307 Perform the TLS handshake between two :py:class:`Connection` instances
308 connected to each other via memory BIOs.
309 """
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400310 client_conn.set_connect_state()
311 server_conn.set_accept_state()
312
313 for conn in [client_conn, server_conn]:
314 try:
315 conn.do_handshake()
316 except WantReadError:
317 pass
318
319 self._interactInMemory(client_conn, server_conn)
320
321
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400322class VersionTests(TestCase):
323 """
324 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900325 :py:obj:`OpenSSL.SSL.SSLeay_version` and
326 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400327 """
328 def test_OPENSSL_VERSION_NUMBER(self):
329 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900330 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400331 byte and the patch, fix, minor, and major versions in the
332 nibbles above that.
333 """
334 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
335
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400336 def test_SSLeay_version(self):
337 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900338 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400339 one of a number of version strings based on that indicator.
340 """
341 versions = {}
342 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
343 SSLEAY_PLATFORM, SSLEAY_DIR]:
344 version = SSLeay_version(t)
345 versions[version] = t
346 self.assertTrue(isinstance(version, bytes))
347 self.assertEqual(len(versions), 5)
348
349
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100350@pytest.fixture
351def context():
352 """
353 A simple TLS 1.0 context.
354 """
355 return Context(TLSv1_METHOD)
356
357
358class TestContext(object):
Hynek Schlawackaa861212016-03-13 13:53:48 +0100359 """
360 py.test-based tests for :class:`OpenSSL.SSL.Context`.
361
362 If possible, add new tests here.
363 """
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100364 @pytest.mark.parametrize("cipher_string", [
365 b"hello world:AES128-SHA",
366 u"hello world:AES128-SHA",
367 ])
368 def test_set_cipher_list(self, context, cipher_string):
369 """
Hynek Schlawacka7a63af2016-03-11 12:05:26 +0100370 :meth:`Context.set_cipher_list` accepts both byte and unicode strings
371 for naming the ciphers which connections created with the context
372 object will be able to choose from.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100373 """
374 context.set_cipher_list(cipher_string)
375 conn = Connection(context, None)
376
377 assert "AES128-SHA" in conn.get_cipher_list()
378
379 @pytest.mark.parametrize("cipher_list,error", [
380 (object(), TypeError),
381 ("imaginary-cipher", Error),
382 ])
383 def test_set_cipher_list_wrong_args(self, context, cipher_list, error):
384 """
385 :meth:`Context.set_cipher_list` raises :exc:`TypeError` when passed a
386 non-string argument and raises :exc:`OpenSSL.SSL.Error` when passed an
387 incorrect cipher list string.
388 """
389 with pytest.raises(error):
390 context.set_cipher_list(cipher_list)
391
392
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400393class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400394 """
Hynek Schlawackaa861212016-03-13 13:53:48 +0100395 Unit tests for :class:`OpenSSL.SSL.Context`.
396
397 If possible, add new tests to :class:`TestContext` above.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400398 """
399 def test_method(self):
400 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200401 :py:obj:`Context` can be instantiated with one of
402 :py:obj:`SSLv2_METHOD`, :py:obj:`SSLv3_METHOD`,
403 :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400404 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400405 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400406 methods = [
407 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
408 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400409 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400410
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400411 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
412 for meth in maybe:
413 try:
414 Context(meth)
415 except (Error, ValueError):
416 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
417 # don't. Difficult to say in advance.
418 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400419
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400420 self.assertRaises(TypeError, Context, "")
421 self.assertRaises(ValueError, Context, 10)
422
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200423 @skip_if_py3
424 def test_method_long(self):
425 """
426 On Python 2 :py:class:`Context` accepts values of type
427 :py:obj:`long` as well as :py:obj:`int`.
428 """
429 Context(long(TLSv1_METHOD))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500430
Rick Deane15b1472009-07-09 15:53:42 -0500431 def test_type(self):
432 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200433 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type
434 object and can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500435 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400436 self.assertIdentical(Context, ContextType)
437 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500438
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400439 def test_use_privatekey(self):
440 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200441 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey`
442 instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400443 """
444 key = PKey()
445 key.generate_key(TYPE_RSA, 128)
446 ctx = Context(TLSv1_METHOD)
447 ctx.use_privatekey(key)
448 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400449
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800450 def test_use_privatekey_file_missing(self):
451 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200452 :py:obj:`Context.use_privatekey_file` raises
453 :py:obj:`OpenSSL.SSL.Error` when passed the name of a file which does
454 not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800455 """
456 ctx = Context(TLSv1_METHOD)
457 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
458
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400459 def _use_privatekey_file_test(self, pemfile, filetype):
460 """
461 Verify that calling ``Context.use_privatekey_file`` with the given
462 arguments does not raise an exception.
463 """
464 key = PKey()
465 key.generate_key(TYPE_RSA, 128)
466
467 with open(pemfile, "wt") as pem:
468 pem.write(
469 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
470 )
471
472 ctx = Context(TLSv1_METHOD)
473 ctx.use_privatekey_file(pemfile, filetype)
474
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400475 def test_use_privatekey_file_bytes(self):
476 """
477 A private key can be specified from a file by passing a ``bytes``
478 instance giving the file name to ``Context.use_privatekey_file``.
479 """
480 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400481 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400482 FILETYPE_PEM,
483 )
484
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400485 def test_use_privatekey_file_unicode(self):
486 """
487 A private key can be specified from a file by passing a ``unicode``
488 instance giving the file name to ``Context.use_privatekey_file``.
489 """
490 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400491 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400492 FILETYPE_PEM,
493 )
494
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200495 @skip_if_py3
496 def test_use_privatekey_file_long(self):
497 """
498 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
499 filetype of type :py:obj:`long` as well as :py:obj:`int`.
500 """
501 self._use_privatekey_file_test(self.mktemp(), long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500502
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800503 def test_use_certificate_wrong_args(self):
504 """
505 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200506 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as
507 an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800508 """
509 ctx = Context(TLSv1_METHOD)
510 self.assertRaises(TypeError, ctx.use_certificate)
511 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200512 self.assertRaises(
513 TypeError, ctx.use_certificate, X509(), "hello, world"
514 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800515
516 def test_use_certificate_uninitialized(self):
517 """
518 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
519 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
520 initialized (ie, which does not actually have any certificate data).
521 """
522 ctx = Context(TLSv1_METHOD)
523 self.assertRaises(Error, ctx.use_certificate, X509())
524
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800525 def test_use_certificate(self):
526 """
527 :py:obj:`Context.use_certificate` sets the certificate which will be
528 used to identify connections created using the context.
529 """
530 # TODO
531 # Hard to assert anything. But we could set a privatekey then ask
532 # OpenSSL if the cert and key agree using check_privatekey. Then as
533 # long as check_privatekey works right we're good...
534 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200535 ctx.use_certificate(
536 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
537 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800538
539 def test_use_certificate_file_wrong_args(self):
540 """
541 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
542 called with zero arguments or more than two arguments, or if the first
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200543 argument is not a byte string or the second argumnent is not an
544 integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800545 """
546 ctx = Context(TLSv1_METHOD)
547 self.assertRaises(TypeError, ctx.use_certificate_file)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200548 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile",
549 object())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800550 self.assertRaises(
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200551 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM,
552 object())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800553 self.assertRaises(
554 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
555 self.assertRaises(
556 TypeError, ctx.use_certificate_file, b"somefile", object())
557
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800558 def test_use_certificate_file_missing(self):
559 """
560 :py:obj:`Context.use_certificate_file` raises
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200561 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does
562 not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800563 """
564 ctx = Context(TLSv1_METHOD)
565 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
566
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400567 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800568 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400569 Verify that calling ``Context.use_certificate_file`` with the given
570 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800571 """
572 # TODO
573 # Hard to assert anything. But we could set a privatekey then ask
574 # OpenSSL if the cert and key agree using check_privatekey. Then as
575 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400576 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800577 pem_file.write(cleartextCertificatePEM)
578
579 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400580 ctx.use_certificate_file(certificate_file)
581
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400582 def test_use_certificate_file_bytes(self):
583 """
584 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
585 ``bytes`` filename) which will be used to identify connections created
586 using the context.
587 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400588 filename = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400589 self._use_certificate_file_test(filename)
590
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400591 def test_use_certificate_file_unicode(self):
592 """
593 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
594 ``bytes`` filename) which will be used to identify connections created
595 using the context.
596 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400597 filename = self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400598 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800599
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200600 @skip_if_py3
601 def test_use_certificate_file_long(self):
602 """
603 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
604 filetype of type :py:obj:`long` as well as :py:obj:`int`.
605 """
606 pem_filename = self.mktemp()
607 with open(pem_filename, "wb") as pem_file:
608 pem_file.write(cleartextCertificatePEM)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500609
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200610 ctx = Context(TLSv1_METHOD)
611 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500612
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500613 def test_check_privatekey_valid(self):
614 """
615 :py:obj:`Context.check_privatekey` returns :py:obj:`None` if the
616 :py:obj:`Context` instance has been configured to use a matched key and
617 certificate pair.
618 """
619 key = load_privatekey(FILETYPE_PEM, client_key_pem)
620 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
621 context = Context(TLSv1_METHOD)
622 context.use_privatekey(key)
623 context.use_certificate(cert)
624 self.assertIs(None, context.check_privatekey())
625
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500626 def test_check_privatekey_invalid(self):
627 """
628 :py:obj:`Context.check_privatekey` raises :py:obj:`Error` if the
629 :py:obj:`Context` instance has been configured to use a key and
630 certificate pair which don't relate to each other.
631 """
632 key = load_privatekey(FILETYPE_PEM, client_key_pem)
633 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
634 context = Context(TLSv1_METHOD)
635 context.use_privatekey(key)
636 context.use_certificate(cert)
637 self.assertRaises(Error, context.check_privatekey)
638
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500639 def test_check_privatekey_wrong_args(self):
640 """
641 :py:obj:`Context.check_privatekey` raises :py:obj:`TypeError` if called
642 with other than no arguments.
643 """
644 context = Context(TLSv1_METHOD)
645 self.assertRaises(TypeError, context.check_privatekey, object())
646
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400647 def test_set_app_data_wrong_args(self):
648 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200649 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called
650 with other than one argument.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400651 """
652 context = Context(TLSv1_METHOD)
653 self.assertRaises(TypeError, context.set_app_data)
654 self.assertRaises(TypeError, context.set_app_data, None, None)
655
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400656 def test_get_app_data_wrong_args(self):
657 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200658 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called
659 with any arguments.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400660 """
661 context = Context(TLSv1_METHOD)
662 self.assertRaises(TypeError, context.get_app_data, None)
663
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400664 def test_app_data(self):
665 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200666 :py:obj:`Context.set_app_data` stores an object for later retrieval
667 using :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400668 """
669 app_data = object()
670 context = Context(TLSv1_METHOD)
671 context.set_app_data(app_data)
672 self.assertIdentical(context.get_app_data(), app_data)
673
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400674 def test_set_options_wrong_args(self):
675 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200676 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with
677 the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400678 """
679 context = Context(TLSv1_METHOD)
680 self.assertRaises(TypeError, context.set_options)
681 self.assertRaises(TypeError, context.set_options, None)
682 self.assertRaises(TypeError, context.set_options, 1, None)
683
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500684 def test_set_options(self):
685 """
686 :py:obj:`Context.set_options` returns the new options value.
687 """
688 context = Context(TLSv1_METHOD)
689 options = context.set_options(OP_NO_SSLv2)
690 self.assertTrue(OP_NO_SSLv2 & options)
691
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200692 @skip_if_py3
693 def test_set_options_long(self):
694 """
695 On Python 2 :py:obj:`Context.set_options` accepts values of type
696 :py:obj:`long` as well as :py:obj:`int`.
697 """
698 context = Context(TLSv1_METHOD)
699 options = context.set_options(long(OP_NO_SSLv2))
700 self.assertTrue(OP_NO_SSLv2 & options)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500701
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300702 def test_set_mode_wrong_args(self):
703 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200704 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with
705 the wrong number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300706 """
707 context = Context(TLSv1_METHOD)
708 self.assertRaises(TypeError, context.set_mode)
709 self.assertRaises(TypeError, context.set_mode, None)
710 self.assertRaises(TypeError, context.set_mode, 1, None)
711
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400712 if MODE_RELEASE_BUFFERS is not None:
713 def test_set_mode(self):
714 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200715 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the
716 newly set mode.
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400717 """
718 context = Context(TLSv1_METHOD)
719 self.assertTrue(
720 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500721
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200722 @skip_if_py3
723 def test_set_mode_long(self):
724 """
725 On Python 2 :py:obj:`Context.set_mode` accepts values of type
726 :py:obj:`long` as well as :py:obj:`int`.
727 """
728 context = Context(TLSv1_METHOD)
729 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
730 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400731 else:
732 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
733
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400734 def test_set_timeout_wrong_args(self):
735 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200736 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with
737 the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400738 """
739 context = Context(TLSv1_METHOD)
740 self.assertRaises(TypeError, context.set_timeout)
741 self.assertRaises(TypeError, context.set_timeout, None)
742 self.assertRaises(TypeError, context.set_timeout, 1, None)
743
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400744 def test_get_timeout_wrong_args(self):
745 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200746 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with
747 any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400748 """
749 context = Context(TLSv1_METHOD)
750 self.assertRaises(TypeError, context.get_timeout, None)
751
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400752 def test_timeout(self):
753 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200754 :py:obj:`Context.set_timeout` sets the session timeout for all
755 connections created using the context object.
756 :py:obj:`Context.get_timeout` retrieves this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400757 """
758 context = Context(TLSv1_METHOD)
759 context.set_timeout(1234)
760 self.assertEquals(context.get_timeout(), 1234)
761
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200762 @skip_if_py3
763 def test_timeout_long(self):
764 """
765 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
766 `long` as well as int.
767 """
768 context = Context(TLSv1_METHOD)
769 context.set_timeout(long(1234))
770 self.assertEquals(context.get_timeout(), 1234)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500771
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400772 def test_set_verify_depth_wrong_args(self):
773 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200774 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called
775 with the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400776 """
777 context = Context(TLSv1_METHOD)
778 self.assertRaises(TypeError, context.set_verify_depth)
779 self.assertRaises(TypeError, context.set_verify_depth, None)
780 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
781
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400782 def test_get_verify_depth_wrong_args(self):
783 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200784 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called
785 with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400786 """
787 context = Context(TLSv1_METHOD)
788 self.assertRaises(TypeError, context.get_verify_depth, None)
789
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400790 def test_verify_depth(self):
791 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200792 :py:obj:`Context.set_verify_depth` sets the number of certificates in
793 a chain to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900794 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400795 """
796 context = Context(TLSv1_METHOD)
797 context.set_verify_depth(11)
798 self.assertEquals(context.get_verify_depth(), 11)
799
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200800 @skip_if_py3
801 def test_verify_depth_long(self):
802 """
803 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
804 type `long` as well as int.
805 """
806 context = Context(TLSv1_METHOD)
807 context.set_verify_depth(long(11))
808 self.assertEquals(context.get_verify_depth(), 11)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500809
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400810 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400811 """
812 Write a new private key out to a new file, encrypted using the given
813 passphrase. Return the path to the new file.
814 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400815 key = PKey()
816 key.generate_key(TYPE_RSA, 128)
817 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400818 fObj = open(pemFile, 'w')
819 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
820 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400821 fObj.close()
822 return pemFile
823
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400824 def test_set_passwd_cb_wrong_args(self):
825 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200826 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called
827 with the wrong arguments or with a non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400828 """
829 context = Context(TLSv1_METHOD)
830 self.assertRaises(TypeError, context.set_passwd_cb)
831 self.assertRaises(TypeError, context.set_passwd_cb, None)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200832 self.assertRaises(
833 TypeError, context.set_passwd_cb, lambda: None, None, None
Hynek Schlawack2c013a92015-09-05 19:33:05 +0200834 ) # pragma: nocover
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400835
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400836 def test_set_passwd_cb(self):
837 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200838 :py:obj:`Context.set_passwd_cb` accepts a callable which will be
839 invoked when a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400840 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400841 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400842 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400843 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200844
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400845 def passphraseCallback(maxlen, verify, extra):
846 calledWith.append((maxlen, verify, extra))
847 return passphrase
848 context = Context(TLSv1_METHOD)
849 context.set_passwd_cb(passphraseCallback)
850 context.use_privatekey_file(pemFile)
851 self.assertTrue(len(calledWith), 1)
852 self.assertTrue(isinstance(calledWith[0][0], int))
853 self.assertTrue(isinstance(calledWith[0][1], int))
854 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400855
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400856 def test_passwd_callback_exception(self):
857 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200858 :py:obj:`Context.use_privatekey_file` propagates any exception raised
859 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400860 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400861 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200862
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400863 def passphraseCallback(maxlen, verify, extra):
864 raise RuntimeError("Sorry, I am a fail.")
865
866 context = Context(TLSv1_METHOD)
867 context.set_passwd_cb(passphraseCallback)
868 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
869
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400870 def test_passwd_callback_false(self):
871 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200872 :py:obj:`Context.use_privatekey_file` raises
873 :py:obj:`OpenSSL.SSL.Error` if the passphrase callback returns a false
874 value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400875 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400876 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200877
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400878 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500879 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400880
881 context = Context(TLSv1_METHOD)
882 context.set_passwd_cb(passphraseCallback)
883 self.assertRaises(Error, context.use_privatekey_file, pemFile)
884
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400885 def test_passwd_callback_non_string(self):
886 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200887 :py:obj:`Context.use_privatekey_file` raises
888 :py:obj:`OpenSSL.SSL.Error` if the passphrase callback returns a true
889 non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400890 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400891 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200892
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400893 def passphraseCallback(maxlen, verify, extra):
894 return 10
895
896 context = Context(TLSv1_METHOD)
897 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800898 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400899
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400900 def test_passwd_callback_too_long(self):
901 """
902 If the passphrase returned by the passphrase callback returns a string
903 longer than the indicated maximum length, it is truncated.
904 """
905 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400906 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400907 pemFile = self._write_encrypted_pem(passphrase)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200908
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400909 def passphraseCallback(maxlen, verify, extra):
910 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400911 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400912
913 context = Context(TLSv1_METHOD)
914 context.set_passwd_cb(passphraseCallback)
915 # This shall succeed because the truncated result is the correct
916 # passphrase.
917 context.use_privatekey_file(pemFile)
918
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400919 def test_set_info_callback(self):
920 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200921 :py:obj:`Context.set_info_callback` accepts a callable which will be
922 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400923 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500924 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400925
926 clientSSL = Connection(Context(TLSv1_METHOD), client)
927 clientSSL.set_connect_state()
928
929 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200930
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400931 def info(conn, where, ret):
932 called.append((conn, where, ret))
933 context = Context(TLSv1_METHOD)
934 context.set_info_callback(info)
935 context.use_certificate(
936 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
937 context.use_privatekey(
938 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
939
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400940 serverSSL = Connection(context, server)
941 serverSSL.set_accept_state()
942
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500943 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400944
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500945 # The callback must always be called with a Connection instance as the
946 # first argument. It would probably be better to split this into
947 # separate tests for client and server side info callbacks so we could
948 # assert it is called with the right Connection instance. It would
949 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500950 notConnections = [
951 conn for (conn, where, ret) in called
952 if not isinstance(conn, Connection)]
953 self.assertEqual(
954 [], notConnections,
955 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400956
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400957 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400958 """
959 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400960 its :py:obj:`load_verify_locations` method with the given arguments.
961 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400962 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500963 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400964
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400965 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400966 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400967 # Require that the server certificate verify properly or the
968 # connection will fail.
969 clientContext.set_verify(
970 VERIFY_PEER,
971 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
972
973 clientSSL = Connection(clientContext, client)
974 clientSSL.set_connect_state()
975
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400976 serverContext = Context(TLSv1_METHOD)
977 serverContext.use_certificate(
978 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
979 serverContext.use_privatekey(
980 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
981
982 serverSSL = Connection(serverContext, server)
983 serverSSL.set_accept_state()
984
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400985 # Without load_verify_locations above, the handshake
986 # will fail:
987 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
988 # 'certificate verify failed')]
989 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400990
991 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400992 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400993
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400994 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400995 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400996 Verify that if path to a file containing a certificate is passed to
997 ``Context.load_verify_locations`` for the ``cafile`` parameter, that
998 certificate is used as a trust root for the purposes of verifying
999 connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001000 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001001 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001002 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001003 fObj.close()
1004
1005 self._load_verify_locations_test(cafile)
1006
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001007 def test_load_verify_bytes_cafile(self):
1008 """
1009 :py:obj:`Context.load_verify_locations` accepts a file name as a
1010 ``bytes`` instance and uses the certificates within for verification
1011 purposes.
1012 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001013 cafile = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001014 self._load_verify_cafile(cafile)
1015
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001016 def test_load_verify_unicode_cafile(self):
1017 """
1018 :py:obj:`Context.load_verify_locations` accepts a file name as a
1019 ``unicode`` instance and uses the certificates within for verification
1020 purposes.
1021 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001022 self._load_verify_cafile(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001023 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001024 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001025
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001026 def test_load_verify_invalid_file(self):
1027 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001028 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when
1029 passed a non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001030 """
1031 clientContext = Context(TLSv1_METHOD)
1032 self.assertRaises(
1033 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001034
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001035 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001036 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001037 Verify that if path to a directory containing certificate files is
1038 passed to ``Context.load_verify_locations`` for the ``capath``
1039 parameter, those certificates are used as trust roots for the purposes
1040 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001041 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001042 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001043 # Hash values computed manually with c_rehash to avoid depending on
1044 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1045 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001046 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001047 cafile = join_bytes_or_unicode(capath, name)
1048 with open(cafile, 'w') as fObj:
1049 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001050
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001051 self._load_verify_locations_test(None, capath)
1052
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001053 def test_load_verify_directory_bytes_capath(self):
1054 """
1055 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1056 ``bytes`` instance and uses the certificates within for verification
1057 purposes.
1058 """
1059 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001060 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001061 )
1062
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001063 def test_load_verify_directory_unicode_capath(self):
1064 """
1065 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1066 ``unicode`` instance and uses the certificates within for verification
1067 purposes.
1068 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001069 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001070 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001071 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001072
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001073 def test_load_verify_locations_wrong_args(self):
1074 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001075 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if
1076 called with the wrong number of arguments or with non-:py:obj:`str`
1077 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001078 """
1079 context = Context(TLSv1_METHOD)
1080 self.assertRaises(TypeError, context.load_verify_locations)
1081 self.assertRaises(TypeError, context.load_verify_locations, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001082 self.assertRaises(
1083 TypeError, context.load_verify_locations, object(), object()
1084 )
1085 self.assertRaises(
1086 TypeError, context.load_verify_locations, None, None, None
1087 )
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001088
Hynek Schlawack734d3022015-09-05 19:19:32 +02001089 @pytest.mark.skipif(
1090 platform == "win32",
1091 reason="set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001092 "See LP#404343 and LP#404344."
Hynek Schlawack734d3022015-09-05 19:19:32 +02001093 )
1094 def test_set_default_verify_paths(self):
1095 """
1096 :py:obj:`Context.set_default_verify_paths` causes the
1097 platform-specific CA certificate locations to be used for
1098 verification purposes.
1099 """
1100 # Testing this requires a server with a certificate signed by one
1101 # of the CAs in the platform CA location. Getting one of those
1102 # costs money. Fortunately (or unfortunately, depending on your
1103 # perspective), it's easy to think of a public server on the
1104 # internet which has such a certificate. Connecting to the network
1105 # in a unit test is bad, but it's the only way I can think of to
1106 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001107
Hynek Schlawack734d3022015-09-05 19:19:32 +02001108 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
Hynek Schlawackbf887932015-10-21 17:13:47 +02001109 context = Context(SSLv23_METHOD)
Hynek Schlawack734d3022015-09-05 19:19:32 +02001110 context.set_default_verify_paths()
1111 context.set_verify(
1112 VERIFY_PEER,
1113 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001114
Hynek Schlawack734d3022015-09-05 19:19:32 +02001115 client = socket()
Hynek Schlawackbf887932015-10-21 17:13:47 +02001116 client.connect(("encrypted.google.com", 443))
Hynek Schlawack734d3022015-09-05 19:19:32 +02001117 clientSSL = Connection(context, client)
1118 clientSSL.set_connect_state()
1119 clientSSL.do_handshake()
1120 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
1121 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001122
1123 def test_set_default_verify_paths_signature(self):
1124 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001125 :py:obj:`Context.set_default_verify_paths` takes no arguments and
1126 raises :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001127 """
1128 context = Context(TLSv1_METHOD)
1129 self.assertRaises(TypeError, context.set_default_verify_paths, None)
1130 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
1131 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001132
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001133 def test_add_extra_chain_cert_invalid_cert(self):
1134 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001135 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if
1136 called with other than one argument or if called with an object which
1137 is not an instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001138 """
1139 context = Context(TLSv1_METHOD)
1140 self.assertRaises(TypeError, context.add_extra_chain_cert)
1141 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001142 self.assertRaises(
1143 TypeError, context.add_extra_chain_cert, object(), object()
1144 )
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001145
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001146 def _handshake_test(self, serverContext, clientContext):
1147 """
1148 Verify that a client and server created with the given contexts can
1149 successfully handshake and communicate.
1150 """
1151 serverSocket, clientSocket = socket_pair()
1152
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001153 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001154 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001155
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001156 client = Connection(clientContext, clientSocket)
1157 client.set_connect_state()
1158
1159 # Make them talk to each other.
1160 # self._interactInMemory(client, server)
1161 for i in range(3):
1162 for s in [client, server]:
1163 try:
1164 s.do_handshake()
1165 except WantReadError:
1166 pass
1167
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001168 def test_set_verify_callback_connection_argument(self):
1169 """
1170 The first argument passed to the verify callback is the
1171 :py:class:`Connection` instance for which verification is taking place.
1172 """
1173 serverContext = Context(TLSv1_METHOD)
1174 serverContext.use_privatekey(
1175 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1176 serverContext.use_certificate(
1177 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1178 serverConnection = Connection(serverContext, None)
1179
1180 class VerifyCallback(object):
1181 def callback(self, connection, *args):
1182 self.connection = connection
1183 return 1
1184
1185 verify = VerifyCallback()
1186 clientContext = Context(TLSv1_METHOD)
1187 clientContext.set_verify(VERIFY_PEER, verify.callback)
1188 clientConnection = Connection(clientContext, None)
1189 clientConnection.set_connect_state()
1190
1191 self._handshakeInMemory(clientConnection, serverConnection)
1192
1193 self.assertIdentical(verify.connection, clientConnection)
1194
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001195 def test_set_verify_callback_exception(self):
1196 """
1197 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1198 exception, verification fails and the exception is propagated to the
1199 caller of :py:obj:`Connection.do_handshake`.
1200 """
1201 serverContext = Context(TLSv1_METHOD)
1202 serverContext.use_privatekey(
1203 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1204 serverContext.use_certificate(
1205 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1206
1207 clientContext = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001208
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001209 def verify_callback(*args):
1210 raise Exception("silly verify failure")
1211 clientContext.set_verify(VERIFY_PEER, verify_callback)
1212
1213 exc = self.assertRaises(
1214 Exception, self._handshake_test, serverContext, clientContext)
1215 self.assertEqual("silly verify failure", str(exc))
1216
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001217 def test_add_extra_chain_cert(self):
1218 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001219 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509`
1220 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001221
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001222 See :py:obj:`_create_certificate_chain` for the details of the
1223 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001224
1225 The chain is tested by starting a server with scert and connecting
1226 to it with a client which trusts cacert and requires verification to
1227 succeed.
1228 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001229 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001230 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1231
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001232 # Dump the CA certificate to a file because that's the only way to load
1233 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001234 for cert, name in [(cacert, 'ca.pem'),
1235 (icert, 'i.pem'),
1236 (scert, 's.pem')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001237 with open(join(self.tmpdir, name), 'w') as f:
1238 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001239
Hynek Schlawack1902c012015-04-16 15:06:41 -04001240 for key, name in [(cakey, 'ca.key'),
1241 (ikey, 'i.key'),
1242 (skey, 's.key')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001243 with open(join(self.tmpdir, name), 'w') as f:
1244 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001245
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001246 # Create the server context
1247 serverContext = Context(TLSv1_METHOD)
1248 serverContext.use_privatekey(skey)
1249 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001250 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001251 serverContext.add_extra_chain_cert(icert)
1252
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001253 # Create the client
1254 clientContext = Context(TLSv1_METHOD)
1255 clientContext.set_verify(
1256 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001257 clientContext.load_verify_locations(join(self.tmpdir, "ca.pem"))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001258
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001259 # Try it out.
1260 self._handshake_test(serverContext, clientContext)
1261
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001262 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001263 """
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001264 Verify that :py:obj:`Context.use_certificate_chain_file` reads a
1265 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001266
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001267 The chain is tested by starting a server with scert and connecting to
1268 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001269 succeed.
1270 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001271 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001272 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1273
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001274 makedirs(certdir)
1275
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001276 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1277 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001278
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001279 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001280 with open(chainFile, 'wb') as fObj:
1281 # Most specific to least general.
1282 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1283 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1284 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1285
1286 with open(caFile, 'w') as fObj:
1287 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001288
1289 serverContext = Context(TLSv1_METHOD)
1290 serverContext.use_certificate_chain_file(chainFile)
1291 serverContext.use_privatekey(skey)
1292
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001293 clientContext = Context(TLSv1_METHOD)
1294 clientContext.set_verify(
1295 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001296 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001297
1298 self._handshake_test(serverContext, clientContext)
1299
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001300 def test_use_certificate_chain_file_bytes(self):
1301 """
1302 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1303 an instance of ``bytes``) to specify additional certificates to use to
1304 construct and verify a trust chain.
1305 """
1306 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001307 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001308 )
1309
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001310 def test_use_certificate_chain_file_unicode(self):
1311 """
1312 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1313 an instance of ``unicode``) to specify additional certificates to use
1314 to construct and verify a trust chain.
1315 """
1316 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001317 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001318 )
1319
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001320 def test_use_certificate_chain_file_wrong_args(self):
1321 """
1322 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1323 if passed zero or more than one argument or when passed a non-byte
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001324 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error`
1325 when passed a bad chain file name (for example, the name of a file
1326 which does not exist).
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001327 """
1328 context = Context(TLSv1_METHOD)
1329 self.assertRaises(TypeError, context.use_certificate_chain_file)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001330 self.assertRaises(
1331 TypeError, context.use_certificate_chain_file, object()
1332 )
1333 self.assertRaises(
1334 TypeError, context.use_certificate_chain_file, b"foo", object()
1335 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001336
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001337 self.assertRaises(
1338 Error, context.use_certificate_chain_file, self.mktemp()
1339 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001340
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001341 # XXX load_client_ca
1342 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001343
1344 def test_get_verify_mode_wrong_args(self):
1345 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001346 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called
1347 with any arguments.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001348 """
1349 context = Context(TLSv1_METHOD)
1350 self.assertRaises(TypeError, context.get_verify_mode, None)
1351
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001352 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001353 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001354 :py:obj:`Context.get_verify_mode` returns the verify mode flags
1355 previously passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001356 """
1357 context = Context(TLSv1_METHOD)
1358 self.assertEquals(context.get_verify_mode(), 0)
1359 context.set_verify(
1360 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1361 self.assertEquals(
1362 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1363
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001364 @skip_if_py3
1365 def test_set_verify_mode_long(self):
1366 """
1367 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1368 type :py:obj:`long` as well as :py:obj:`int`.
1369 """
1370 context = Context(TLSv1_METHOD)
1371 self.assertEquals(context.get_verify_mode(), 0)
1372 context.set_verify(
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001373 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None
1374 ) # pragma: nocover
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001375 self.assertEquals(
1376 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001377
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001378 def test_load_tmp_dh_wrong_args(self):
1379 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001380 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with
1381 the wrong number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001382 """
1383 context = Context(TLSv1_METHOD)
1384 self.assertRaises(TypeError, context.load_tmp_dh)
1385 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1386 self.assertRaises(TypeError, context.load_tmp_dh, object())
1387
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001388 def test_load_tmp_dh_missing_file(self):
1389 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001390 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the
1391 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001392 """
1393 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001394 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001395
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001396 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001397 """
1398 Verify that calling ``Context.load_tmp_dh`` with the given filename
1399 does not raise an exception.
1400 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001401 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001402 with open(dhfilename, "w") as dhfile:
1403 dhfile.write(dhparam)
1404
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001405 context.load_tmp_dh(dhfilename)
1406 # XXX What should I assert here? -exarkun
1407
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001408 def test_load_tmp_dh_bytes(self):
1409 """
1410 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1411 specified file (given as ``bytes``).
1412 """
1413 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001414 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001415 )
1416
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001417 def test_load_tmp_dh_unicode(self):
1418 """
1419 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1420 specified file (given as ``unicode``).
1421 """
1422 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001423 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001424 )
1425
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001426 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001427 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001428 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001429 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001430 """
1431 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001432 for curve in get_elliptic_curves():
Hynek Schlawacka07fa8c2015-10-17 10:15:28 +02001433 if curve.name.startswith(u"Oakley-"):
Hynek Schlawack7408aff2015-10-17 09:51:16 +02001434 # Setting Oakley-EC2N-4 and Oakley-EC2N-3 adds
1435 # ('bignum routines', 'BN_mod_inverse', 'no inverse') to the
1436 # error queue on OpenSSL 1.0.2.
1437 continue
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001438 # The only easily "assertable" thing is that it does not raise an
1439 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001440 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001441
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001442 def test_set_session_cache_mode_wrong_args(self):
1443 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001444 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1445 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001446 """
1447 context = Context(TLSv1_METHOD)
1448 self.assertRaises(TypeError, context.set_session_cache_mode)
1449 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1450
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001451 def test_get_session_cache_mode_wrong_args(self):
1452 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001453 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1454 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001455 """
1456 context = Context(TLSv1_METHOD)
1457 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1458
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001459 def test_session_cache_mode(self):
1460 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001461 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1462 cached. The setting can be retrieved via
1463 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001464 """
1465 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001466 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001467 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1468 self.assertEqual(SESS_CACHE_OFF, off)
1469 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1470
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001471 @skip_if_py3
1472 def test_session_cache_mode_long(self):
1473 """
1474 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1475 of type :py:obj:`long` as well as :py:obj:`int`.
1476 """
1477 context = Context(TLSv1_METHOD)
1478 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1479 self.assertEqual(
1480 SESS_CACHE_BOTH, context.get_session_cache_mode())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001481
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001482 def test_get_cert_store(self):
1483 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001484 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store`
1485 instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001486 """
1487 context = Context(TLSv1_METHOD)
1488 store = context.get_cert_store()
1489 self.assertIsInstance(store, X509Store)
1490
1491
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001492class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1493 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001494 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its
1495 interaction with :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001496 """
1497 def test_wrong_args(self):
1498 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001499 :py:obj:`Context.set_tlsext_servername_callback` raises
1500 :py:obj:`TypeError` if called with other than one argument.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001501 """
1502 context = Context(TLSv1_METHOD)
1503 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1504 self.assertRaises(
1505 TypeError, context.set_tlsext_servername_callback, 1, 2)
1506
1507 def test_old_callback_forgotten(self):
1508 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001509 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify
1510 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001511 """
1512 def callback(connection):
1513 pass
1514
1515 def replacement(connection):
1516 pass
1517
1518 context = Context(TLSv1_METHOD)
1519 context.set_tlsext_servername_callback(callback)
1520
1521 tracker = ref(callback)
1522 del callback
1523
1524 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001525
1526 # One run of the garbage collector happens to work on CPython. PyPy
1527 # doesn't collect the underlying object until a second run for whatever
1528 # reason. That's fine, it still demonstrates our code has properly
1529 # dropped the reference.
1530 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001531 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001532
1533 callback = tracker()
1534 if callback is not None:
1535 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001536 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001537 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001538
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001539 def test_no_servername(self):
1540 """
1541 When a client specifies no server name, the callback passed to
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001542 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the
1543 result of :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001544 """
1545 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001546
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001547 def servername(conn):
1548 args.append((conn, conn.get_servername()))
1549 context = Context(TLSv1_METHOD)
1550 context.set_tlsext_servername_callback(servername)
1551
1552 # Lose our reference to it. The Context is responsible for keeping it
1553 # alive now.
1554 del servername
1555 collect()
1556
1557 # Necessary to actually accept the connection
1558 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001559 context.use_certificate(
1560 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001561
1562 # Do a little connection to trigger the logic
1563 server = Connection(context, None)
1564 server.set_accept_state()
1565
1566 client = Connection(Context(TLSv1_METHOD), None)
1567 client.set_connect_state()
1568
1569 self._interactInMemory(server, client)
1570
1571 self.assertEqual([(server, None)], args)
1572
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001573 def test_servername(self):
1574 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001575 When a client specifies a server name in its hello message, the
1576 callback passed to :py:obj:`Contexts.set_tlsext_servername_callback` is
1577 invoked and the result of :py:obj:`Connection.get_servername` is that
1578 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001579 """
1580 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001581
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001582 def servername(conn):
1583 args.append((conn, conn.get_servername()))
1584 context = Context(TLSv1_METHOD)
1585 context.set_tlsext_servername_callback(servername)
1586
1587 # Necessary to actually accept the connection
1588 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001589 context.use_certificate(
1590 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001591
1592 # Do a little connection to trigger the logic
1593 server = Connection(context, None)
1594 server.set_accept_state()
1595
1596 client = Connection(Context(TLSv1_METHOD), None)
1597 client.set_connect_state()
1598 client.set_tlsext_host_name(b("foo1.example.com"))
1599
1600 self._interactInMemory(server, client)
1601
1602 self.assertEqual([(server, b("foo1.example.com"))], args)
1603
1604
Cory Benfield84a121e2014-03-31 20:30:25 +01001605class NextProtoNegotiationTests(TestCase, _LoopbackMixin):
1606 """
1607 Test for Next Protocol Negotiation in PyOpenSSL.
1608 """
Cory Benfieldba1820d2015-04-13 17:39:12 -04001609 if _lib.Cryptography_HAS_NEXTPROTONEG:
1610 def test_npn_success(self):
1611 """
1612 Tests that clients and servers that agree on the negotiated next
1613 protocol can correct establish a connection, and that the agreed
1614 protocol is reported by the connections.
1615 """
1616 advertise_args = []
1617 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001618
Cory Benfieldba1820d2015-04-13 17:39:12 -04001619 def advertise(conn):
1620 advertise_args.append((conn,))
1621 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001622
Cory Benfieldba1820d2015-04-13 17:39:12 -04001623 def select(conn, options):
1624 select_args.append((conn, options))
1625 return b'spdy/2'
Cory Benfield84a121e2014-03-31 20:30:25 +01001626
Cory Benfieldba1820d2015-04-13 17:39:12 -04001627 server_context = Context(TLSv1_METHOD)
1628 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001629
Cory Benfieldba1820d2015-04-13 17:39:12 -04001630 client_context = Context(TLSv1_METHOD)
1631 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001632
Cory Benfieldba1820d2015-04-13 17:39:12 -04001633 # Necessary to actually accept the connection
1634 server_context.use_privatekey(
1635 load_privatekey(FILETYPE_PEM, server_key_pem))
1636 server_context.use_certificate(
1637 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001638
Cory Benfieldba1820d2015-04-13 17:39:12 -04001639 # Do a little connection to trigger the logic
1640 server = Connection(server_context, None)
1641 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001642
Cory Benfieldba1820d2015-04-13 17:39:12 -04001643 client = Connection(client_context, None)
1644 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001645
Cory Benfieldba1820d2015-04-13 17:39:12 -04001646 self._interactInMemory(server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001647
Cory Benfieldba1820d2015-04-13 17:39:12 -04001648 self.assertEqual([(server,)], advertise_args)
1649 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001650
Cory Benfieldba1820d2015-04-13 17:39:12 -04001651 self.assertEqual(server.get_next_proto_negotiated(), b'spdy/2')
1652 self.assertEqual(client.get_next_proto_negotiated(), b'spdy/2')
Cory Benfield84a121e2014-03-31 20:30:25 +01001653
Cory Benfieldba1820d2015-04-13 17:39:12 -04001654 def test_npn_client_fail(self):
1655 """
1656 Tests that when clients and servers cannot agree on what protocol
1657 to use next that the TLS connection does not get established.
1658 """
1659 advertise_args = []
1660 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001661
Cory Benfieldba1820d2015-04-13 17:39:12 -04001662 def advertise(conn):
1663 advertise_args.append((conn,))
1664 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001665
Cory Benfieldba1820d2015-04-13 17:39:12 -04001666 def select(conn, options):
1667 select_args.append((conn, options))
1668 return b''
Cory Benfield84a121e2014-03-31 20:30:25 +01001669
Cory Benfieldba1820d2015-04-13 17:39:12 -04001670 server_context = Context(TLSv1_METHOD)
1671 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001672
Cory Benfieldba1820d2015-04-13 17:39:12 -04001673 client_context = Context(TLSv1_METHOD)
1674 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001675
Cory Benfieldba1820d2015-04-13 17:39:12 -04001676 # Necessary to actually accept the connection
1677 server_context.use_privatekey(
1678 load_privatekey(FILETYPE_PEM, server_key_pem))
1679 server_context.use_certificate(
1680 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001681
Cory Benfieldba1820d2015-04-13 17:39:12 -04001682 # Do a little connection to trigger the logic
1683 server = Connection(server_context, None)
1684 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001685
Cory Benfieldba1820d2015-04-13 17:39:12 -04001686 client = Connection(client_context, None)
1687 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001688
Cory Benfieldba1820d2015-04-13 17:39:12 -04001689 # If the client doesn't return anything, the connection will fail.
1690 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001691
Cory Benfieldba1820d2015-04-13 17:39:12 -04001692 self.assertEqual([(server,)], advertise_args)
1693 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001694
Cory Benfieldba1820d2015-04-13 17:39:12 -04001695 def test_npn_select_error(self):
1696 """
1697 Test that we can handle exceptions in the select callback. If
1698 select fails it should be fatal to the connection.
1699 """
1700 advertise_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 raise TypeError
Cory Benfield0ea76e72015-03-22 09:05:28 +00001708
Cory Benfieldba1820d2015-04-13 17:39:12 -04001709 server_context = Context(TLSv1_METHOD)
1710 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001711
Cory Benfieldba1820d2015-04-13 17:39:12 -04001712 client_context = Context(TLSv1_METHOD)
1713 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001714
Cory Benfieldba1820d2015-04-13 17:39:12 -04001715 # Necessary to actually accept the connection
1716 server_context.use_privatekey(
1717 load_privatekey(FILETYPE_PEM, server_key_pem))
1718 server_context.use_certificate(
1719 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001720
Cory Benfieldba1820d2015-04-13 17:39:12 -04001721 # Do a little connection to trigger the logic
1722 server = Connection(server_context, None)
1723 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001724
Cory Benfieldba1820d2015-04-13 17:39:12 -04001725 client = Connection(client_context, None)
1726 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001727
Cory Benfieldba1820d2015-04-13 17:39:12 -04001728 # If the callback throws an exception it should be raised here.
1729 self.assertRaises(
1730 TypeError, self._interactInMemory, server, client
1731 )
1732 self.assertEqual([(server,)], advertise_args)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001733
Cory Benfieldba1820d2015-04-13 17:39:12 -04001734 def test_npn_advertise_error(self):
1735 """
1736 Test that we can handle exceptions in the advertise callback. If
1737 advertise fails no NPN is advertised to the client.
1738 """
1739 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001740
Cory Benfieldba1820d2015-04-13 17:39:12 -04001741 def advertise(conn):
1742 raise TypeError
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001743
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001744 def select(conn, options): # pragma: nocover
1745 """
1746 Assert later that no args are actually appended.
1747 """
Cory Benfieldba1820d2015-04-13 17:39:12 -04001748 select_args.append((conn, options))
1749 return b''
Cory Benfield0ea76e72015-03-22 09:05:28 +00001750
Cory Benfieldba1820d2015-04-13 17:39:12 -04001751 server_context = Context(TLSv1_METHOD)
1752 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001753
Cory Benfieldba1820d2015-04-13 17:39:12 -04001754 client_context = Context(TLSv1_METHOD)
1755 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001756
Cory Benfieldba1820d2015-04-13 17:39:12 -04001757 # Necessary to actually accept the connection
1758 server_context.use_privatekey(
1759 load_privatekey(FILETYPE_PEM, server_key_pem))
1760 server_context.use_certificate(
1761 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001762
Cory Benfieldba1820d2015-04-13 17:39:12 -04001763 # Do a little connection to trigger the logic
1764 server = Connection(server_context, None)
1765 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001766
Cory Benfieldba1820d2015-04-13 17:39:12 -04001767 client = Connection(client_context, None)
1768 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001769
Cory Benfieldba1820d2015-04-13 17:39:12 -04001770 # If the client doesn't return anything, the connection will fail.
1771 self.assertRaises(
1772 TypeError, self._interactInMemory, server, client
1773 )
1774 self.assertEqual([], select_args)
1775
1776 else:
1777 # No NPN.
1778 def test_npn_not_implemented(self):
1779 # Test the context methods first.
1780 context = Context(TLSv1_METHOD)
1781 fail_methods = [
1782 context.set_npn_advertise_callback,
1783 context.set_npn_select_callback,
1784 ]
1785 for method in fail_methods:
1786 self.assertRaises(
1787 NotImplementedError, method, None
1788 )
1789
1790 # Now test a connection.
1791 conn = Connection(context)
1792 fail_methods = [
1793 conn.get_next_proto_negotiated,
1794 ]
1795 for method in fail_methods:
1796 self.assertRaises(NotImplementedError, method)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001797
1798
Cory Benfield12eae892014-06-07 15:42:56 +01001799class ApplicationLayerProtoNegotiationTests(TestCase, _LoopbackMixin):
1800 """
1801 Tests for ALPN in PyOpenSSL.
1802 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001803 # Skip tests on versions that don't support ALPN.
1804 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001805
Cory Benfielde46fa842015-04-13 16:50:49 -04001806 def test_alpn_success(self):
1807 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001808 Clients and servers that agree on the negotiated ALPN protocol can
1809 correct establish a connection, and the agreed protocol is reported
1810 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001811 """
1812 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001813
Cory Benfielde46fa842015-04-13 16:50:49 -04001814 def select(conn, options):
1815 select_args.append((conn, options))
1816 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001817
Cory Benfielde46fa842015-04-13 16:50:49 -04001818 client_context = Context(TLSv1_METHOD)
1819 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001820
Cory Benfielde46fa842015-04-13 16:50:49 -04001821 server_context = Context(TLSv1_METHOD)
1822 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001823
Cory Benfielde46fa842015-04-13 16:50:49 -04001824 # Necessary to actually accept the connection
1825 server_context.use_privatekey(
1826 load_privatekey(FILETYPE_PEM, server_key_pem))
1827 server_context.use_certificate(
1828 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001829
Cory Benfielde46fa842015-04-13 16:50:49 -04001830 # Do a little connection to trigger the logic
1831 server = Connection(server_context, None)
1832 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001833
Cory Benfielde46fa842015-04-13 16:50:49 -04001834 client = Connection(client_context, None)
1835 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001836
Cory Benfielde46fa842015-04-13 16:50:49 -04001837 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001838
Cory Benfielde46fa842015-04-13 16:50:49 -04001839 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
1840
1841 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1842 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001843
Cory Benfielde46fa842015-04-13 16:50:49 -04001844 def test_alpn_set_on_connection(self):
1845 """
1846 The same as test_alpn_success, but setting the ALPN protocols on
1847 the connection rather than the context.
1848 """
1849 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001850
Cory Benfielde46fa842015-04-13 16:50:49 -04001851 def select(conn, options):
1852 select_args.append((conn, options))
1853 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001854
Cory Benfielde46fa842015-04-13 16:50:49 -04001855 # Setup the client context but don't set any ALPN protocols.
1856 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001857
Cory Benfielde46fa842015-04-13 16:50:49 -04001858 server_context = Context(TLSv1_METHOD)
1859 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001860
Cory Benfielde46fa842015-04-13 16:50:49 -04001861 # Necessary to actually accept the connection
1862 server_context.use_privatekey(
1863 load_privatekey(FILETYPE_PEM, server_key_pem))
1864 server_context.use_certificate(
1865 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001866
Cory Benfielde46fa842015-04-13 16:50:49 -04001867 # Do a little connection to trigger the logic
1868 server = Connection(server_context, None)
1869 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001870
Cory Benfielde46fa842015-04-13 16:50:49 -04001871 # Set the ALPN protocols on the client connection.
1872 client = Connection(client_context, None)
1873 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1874 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001875
Cory Benfielde46fa842015-04-13 16:50:49 -04001876 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001877
Cory Benfielde46fa842015-04-13 16:50:49 -04001878 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001879
Cory Benfielde46fa842015-04-13 16:50:49 -04001880 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1881 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001882
Cory Benfielde46fa842015-04-13 16:50:49 -04001883 def test_alpn_server_fail(self):
1884 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001885 When clients and servers cannot agree on what protocol to use next
1886 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001887 """
1888 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001889
Cory Benfielde46fa842015-04-13 16:50:49 -04001890 def select(conn, options):
1891 select_args.append((conn, options))
1892 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001893
Cory Benfielde46fa842015-04-13 16:50:49 -04001894 client_context = Context(TLSv1_METHOD)
1895 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001896
Cory Benfielde46fa842015-04-13 16:50:49 -04001897 server_context = Context(TLSv1_METHOD)
1898 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001899
Cory Benfielde46fa842015-04-13 16:50:49 -04001900 # Necessary to actually accept the connection
1901 server_context.use_privatekey(
1902 load_privatekey(FILETYPE_PEM, server_key_pem))
1903 server_context.use_certificate(
1904 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001905
Cory Benfielde46fa842015-04-13 16:50:49 -04001906 # Do a little connection to trigger the logic
1907 server = Connection(server_context, None)
1908 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001909
Cory Benfielde46fa842015-04-13 16:50:49 -04001910 client = Connection(client_context, None)
1911 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001912
Cory Benfielde46fa842015-04-13 16:50:49 -04001913 # If the client doesn't return anything, the connection will fail.
1914 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001915
Cory Benfielde46fa842015-04-13 16:50:49 -04001916 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001917
Cory Benfielde46fa842015-04-13 16:50:49 -04001918 def test_alpn_no_server(self):
1919 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001920 When clients and servers cannot agree on what protocol to use next
1921 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04001922 """
1923 client_context = Context(TLSv1_METHOD)
1924 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04001925
Cory Benfielde46fa842015-04-13 16:50:49 -04001926 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04001927
Cory Benfielde46fa842015-04-13 16:50:49 -04001928 # Necessary to actually accept the connection
1929 server_context.use_privatekey(
1930 load_privatekey(FILETYPE_PEM, server_key_pem))
1931 server_context.use_certificate(
1932 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04001933
Cory Benfielde46fa842015-04-13 16:50:49 -04001934 # Do a little connection to trigger the logic
1935 server = Connection(server_context, None)
1936 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001937
Cory Benfielde46fa842015-04-13 16:50:49 -04001938 client = Connection(client_context, None)
1939 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001940
Cory Benfielde46fa842015-04-13 16:50:49 -04001941 # Do the dance.
1942 self._interactInMemory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04001943
Cory Benfielde46fa842015-04-13 16:50:49 -04001944 self.assertEqual(client.get_alpn_proto_negotiated(), b'')
Cory Benfielde3d57152015-04-11 17:57:35 -04001945
Cory Benfielde46fa842015-04-13 16:50:49 -04001946 def test_alpn_callback_exception(self):
1947 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001948 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04001949 """
1950 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001951
Cory Benfielde46fa842015-04-13 16:50:49 -04001952 def select(conn, options):
1953 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04001954 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001955
Cory Benfielde46fa842015-04-13 16:50:49 -04001956 client_context = Context(TLSv1_METHOD)
1957 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04001958
Cory Benfielde46fa842015-04-13 16:50:49 -04001959 server_context = Context(TLSv1_METHOD)
1960 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04001961
Cory Benfielde46fa842015-04-13 16:50:49 -04001962 # Necessary to actually accept the connection
1963 server_context.use_privatekey(
1964 load_privatekey(FILETYPE_PEM, server_key_pem))
1965 server_context.use_certificate(
1966 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04001967
Cory Benfielde46fa842015-04-13 16:50:49 -04001968 # Do a little connection to trigger the logic
1969 server = Connection(server_context, None)
1970 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001971
Cory Benfielde46fa842015-04-13 16:50:49 -04001972 client = Connection(client_context, None)
1973 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001974
Cory Benfielde46fa842015-04-13 16:50:49 -04001975 self.assertRaises(
1976 TypeError, self._interactInMemory, server, client
1977 )
1978 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfieldf1177e72015-04-12 09:11:49 -04001979
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001980 else:
1981 # No ALPN.
1982 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04001983 """
1984 If ALPN is not in OpenSSL, we should raise NotImplementedError.
1985 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001986 # Test the context methods first.
1987 context = Context(TLSv1_METHOD)
Cory Benfield307e9e62015-04-13 18:21:12 -04001988 self.assertRaises(
1989 NotImplementedError, context.set_alpn_protos, None
1990 )
1991 self.assertRaises(
1992 NotImplementedError, context.set_alpn_select_callback, None
1993 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001994
1995 # Now test a connection.
1996 conn = Connection(context)
Cory Benfield307e9e62015-04-13 18:21:12 -04001997 self.assertRaises(
Alex Gaynor68417232015-09-04 07:56:29 -04001998 NotImplementedError, conn.set_alpn_protos, None
Cory Benfield307e9e62015-04-13 18:21:12 -04001999 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002000
Cory Benfieldf1177e72015-04-12 09:11:49 -04002001
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002002class SessionTests(TestCase):
2003 """
2004 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
2005 """
2006 def test_construction(self):
2007 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002008 :py:class:`Session` can be constructed with no arguments, creating
2009 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002010 """
2011 new_session = Session()
2012 self.assertTrue(isinstance(new_session, Session))
2013
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002014 def test_construction_wrong_args(self):
2015 """
2016 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
2017 is raised.
2018 """
2019 self.assertRaises(TypeError, Session, 123)
2020 self.assertRaises(TypeError, Session, "hello")
2021 self.assertRaises(TypeError, Session, object())
2022
2023
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002024class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05002025 """
Hynek Schlawackaa861212016-03-13 13:53:48 +01002026 Unit tests for :class:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002027 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002028 # XXX get_peer_certificate -> None
2029 # XXX sock_shutdown
2030 # XXX master_key -> TypeError
2031 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002032 # XXX connect -> TypeError
2033 # XXX connect_ex -> TypeError
2034 # XXX set_connect_state -> TypeError
2035 # XXX set_accept_state -> TypeError
2036 # XXX renegotiate_pending
2037 # XXX do_handshake -> TypeError
2038 # XXX bio_read -> TypeError
2039 # XXX recv -> TypeError
2040 # XXX send -> TypeError
2041 # XXX bio_write -> TypeError
2042
Rick Deane15b1472009-07-09 15:53:42 -05002043 def test_type(self):
2044 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002045 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same
2046 type object and can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002047 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002048 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05002049 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002050 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002051
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002052 def test_get_context(self):
2053 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002054 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance
2055 used to construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002056 """
2057 context = Context(TLSv1_METHOD)
2058 connection = Connection(context, None)
2059 self.assertIdentical(connection.get_context(), context)
2060
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002061 def test_get_context_wrong_args(self):
2062 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002063 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called
2064 with any arguments.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002065 """
2066 connection = Connection(Context(TLSv1_METHOD), None)
2067 self.assertRaises(TypeError, connection.get_context, None)
2068
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002069 def test_set_context_wrong_args(self):
2070 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002071 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called
2072 with a non-:py:obj:`Context` instance argument or with any number of
2073 arguments other than 1.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002074 """
2075 ctx = Context(TLSv1_METHOD)
2076 connection = Connection(ctx, None)
2077 self.assertRaises(TypeError, connection.set_context)
2078 self.assertRaises(TypeError, connection.set_context, object())
2079 self.assertRaises(TypeError, connection.set_context, "hello")
2080 self.assertRaises(TypeError, connection.set_context, 1)
2081 self.assertRaises(TypeError, connection.set_context, 1, 2)
2082 self.assertRaises(
2083 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
2084 self.assertIdentical(ctx, connection.get_context())
2085
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002086 def test_set_context(self):
2087 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002088 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context`
2089 instance to be used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002090 """
2091 original = Context(SSLv23_METHOD)
2092 replacement = Context(TLSv1_METHOD)
2093 connection = Connection(original, None)
2094 connection.set_context(replacement)
2095 self.assertIdentical(replacement, connection.get_context())
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002096 # Lose our references to the contexts, just in case the Connection
2097 # isn't properly managing its own contributions to their reference
2098 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002099 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002100 collect()
2101
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002102 def test_set_tlsext_host_name_wrong_args(self):
2103 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002104 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte
2105 string argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09002106 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002107 """
2108 conn = Connection(Context(TLSv1_METHOD), None)
2109 self.assertRaises(TypeError, conn.set_tlsext_host_name)
2110 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
2111 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
2112 self.assertRaises(
2113 TypeError, conn.set_tlsext_host_name, b("with\0null"))
2114
Abraham Martinc5484ba2015-03-25 15:33:05 +00002115 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002116 # On Python 3.x, don't accidentally implicitly convert from text.
2117 self.assertRaises(
2118 TypeError,
2119 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002120
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002121 def test_get_servername_wrong_args(self):
2122 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002123 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if
2124 called with any arguments.
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002125 """
2126 connection = Connection(Context(TLSv1_METHOD), None)
2127 self.assertRaises(TypeError, connection.get_servername, object())
2128 self.assertRaises(TypeError, connection.get_servername, 1)
2129 self.assertRaises(TypeError, connection.get_servername, "hello")
2130
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002131 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002132 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002133 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002134 immediate read.
2135 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002136 connection = Connection(Context(TLSv1_METHOD), None)
2137 self.assertEquals(connection.pending(), 0)
2138
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002139 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002140 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002141 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with
2142 any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002143 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002144 connection = Connection(Context(TLSv1_METHOD), None)
2145 self.assertRaises(TypeError, connection.pending, None)
2146
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002147 def test_peek(self):
2148 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002149 :py:obj:`Connection.recv` peeks into the connection if
2150 :py:obj:`socket.MSG_PEEK` is passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002151 """
2152 server, client = self._loopback()
2153 server.send(b('xy'))
2154 self.assertEqual(client.recv(2, MSG_PEEK), b('xy'))
2155 self.assertEqual(client.recv(2, MSG_PEEK), b('xy'))
2156 self.assertEqual(client.recv(2), b('xy'))
2157
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002158 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002159 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002160 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with
2161 a non-address argument or with the wrong number of arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002162 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002163 connection = Connection(Context(TLSv1_METHOD), socket())
2164 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002165 self.assertRaises(TypeError, connection.connect)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002166 self.assertRaises(
2167 TypeError, connection.connect, ("127.0.0.1", 1), None
2168 )
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002169
kjavfe508d62015-09-02 12:20:35 +01002170 def test_connection_undefined_attr(self):
2171 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002172 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with
2173 a non-address argument or with the wrong number of arguments.
kjavfe508d62015-09-02 12:20:35 +01002174 """
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002175
kjavfe508d62015-09-02 12:20:35 +01002176 def attr_access_test(connection):
2177 return connection.an_attribute_which_is_not_defined
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002178
kjavfe508d62015-09-02 12:20:35 +01002179 connection = Connection(Context(TLSv1_METHOD), None)
2180 self.assertRaises(AttributeError, attr_access_test, connection)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002181
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002182 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002183 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002184 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the
2185 underlying socket connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002186 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002187 client = socket()
2188 context = Context(TLSv1_METHOD)
2189 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002190 # pytest.raises here doesn't work because of a bug in py.test on Python
2191 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002192 try:
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002193 clientSSL.connect(("127.0.0.1", 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002194 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002195 exc = e
2196 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002197
2198 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002199 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002200 :py:obj:`Connection.connect` establishes a connection to the specified
2201 address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002202 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002203 port = socket()
2204 port.bind(('', 0))
2205 port.listen(3)
2206
2207 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002208 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2209 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002210
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002211 @pytest.mark.skipif(
2212 platform == "darwin",
2213 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2214 )
2215 def test_connect_ex(self):
2216 """
2217 If there is a connection error, :py:obj:`Connection.connect_ex`
2218 returns the errno instead of raising an exception.
2219 """
2220 port = socket()
2221 port.bind(('', 0))
2222 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002223
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002224 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2225 clientSSL.setblocking(False)
2226 result = clientSSL.connect_ex(port.getsockname())
2227 expected = (EINPROGRESS, EWOULDBLOCK)
2228 self.assertTrue(
2229 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002230
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002231 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002232 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002233 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with
2234 any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002235 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002236 connection = Connection(Context(TLSv1_METHOD), socket())
2237 self.assertRaises(TypeError, connection.accept, None)
2238
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002239 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002240 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002241 :py:obj:`Connection.accept` accepts a pending connection attempt and
2242 returns a tuple of a new :py:obj:`Connection` (the accepted client) and
2243 the address the connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002244 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002245 ctx = Context(TLSv1_METHOD)
2246 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2247 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002248 port = socket()
2249 portSSL = Connection(ctx, port)
2250 portSSL.bind(('', 0))
2251 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002252
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002253 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002254
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002255 # Calling portSSL.getsockname() here to get the server IP address
2256 # sounds great, but frequently fails on Windows.
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002257 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002258
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002259 serverSSL, address = portSSL.accept()
2260
2261 self.assertTrue(isinstance(serverSSL, Connection))
2262 self.assertIdentical(serverSSL.get_context(), ctx)
2263 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002264
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002265 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002266 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002267 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with
2268 the wrong number of arguments or with arguments other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002269 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002270 connection = Connection(Context(TLSv1_METHOD), None)
2271 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04002272 self.assertRaises(TypeError, connection.get_shutdown, None)
2273 self.assertRaises(TypeError, connection.set_shutdown)
2274 self.assertRaises(TypeError, connection.set_shutdown, None)
2275 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002276
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002277 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002278 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002279 :py:obj:`Connection.shutdown` performs an SSL-level connection
2280 shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002281 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002282 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002283 self.assertFalse(server.shutdown())
2284 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002285 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002286 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
2287 client.shutdown()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002288 self.assertEquals(
2289 client.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN
2290 )
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002291 self.assertRaises(ZeroReturnError, server.recv, 1024)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002292 self.assertEquals(
2293 server.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN
2294 )
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002295
Paul Aurichc85e0862015-01-08 08:34:33 -08002296 def test_shutdown_closed(self):
2297 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002298 If the underlying socket is closed, :py:obj:`Connection.shutdown`
2299 propagates the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002300 """
2301 server, client = self._loopback()
2302 server.sock_shutdown(2)
2303 exc = self.assertRaises(SysCallError, server.shutdown)
2304 if platform == "win32":
2305 self.assertEqual(exc.args[0], ESHUTDOWN)
2306 else:
2307 self.assertEqual(exc.args[0], EPIPE)
2308
Glyph89389472015-04-14 17:29:26 -04002309 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002310 """
Glyph89389472015-04-14 17:29:26 -04002311 If the underlying connection is truncated, :obj:`Connection.shutdown`
2312 raises an :obj:`Error`.
Glyph6064ec32015-04-14 16:38:22 -04002313 """
Glyph89389472015-04-14 17:29:26 -04002314 server_ctx = Context(TLSv1_METHOD)
2315 client_ctx = Context(TLSv1_METHOD)
2316 server_ctx.use_privatekey(
2317 load_privatekey(FILETYPE_PEM, server_key_pem))
2318 server_ctx.use_certificate(
2319 load_certificate(FILETYPE_PEM, server_cert_pem))
2320 server = Connection(server_ctx, None)
2321 client = Connection(client_ctx, None)
2322 self._handshakeInMemory(client, server)
2323 self.assertEqual(server.shutdown(), False)
2324 self.assertRaises(WantReadError, server.shutdown)
2325 server.bio_shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002326 self.assertRaises(Error, server.shutdown)
2327
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002328 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002329 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002330 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection
2331 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002332 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002333 connection = Connection(Context(TLSv1_METHOD), socket())
2334 connection.set_shutdown(RECEIVED_SHUTDOWN)
2335 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2336
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002337 @skip_if_py3
2338 def test_set_shutdown_long(self):
2339 """
2340 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
2341 of type :py:obj:`long` as well as :py:obj:`int`.
2342 """
2343 connection = Connection(Context(TLSv1_METHOD), socket())
2344 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
2345 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002346
kjavaf248592015-09-07 12:14:01 +01002347 def test_state_string(self):
2348 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002349 :meth:`Connection.state_string` verbosely describes the current
2350 state of the :class:`Connection`.
kjavaf248592015-09-07 12:14:01 +01002351 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002352 server, client = socket_pair()
kjavaf248592015-09-07 12:14:01 +01002353 server = self._loopbackServerFactory(server)
2354 client = self._loopbackClientFactory(client)
2355
Hynek Schlawacka5811cc2016-01-31 13:52:42 +01002356 assert b"before/accept initialization" == server.state_string()
2357 assert b"before/connect initialization" == client.state_string()
kjavaf248592015-09-07 12:14:01 +01002358
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002359 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002360 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002361 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called
2362 with other than one argument. :py:obj:`Connection.get_app_data` raises
2363 :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002364 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002365 conn = Connection(Context(TLSv1_METHOD), None)
2366 self.assertRaises(TypeError, conn.get_app_data, None)
2367 self.assertRaises(TypeError, conn.set_app_data)
2368 self.assertRaises(TypeError, conn.set_app_data, None, None)
2369
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002370 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002371 """
2372 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002373 :py:obj:`Connection.set_app_data` and later retrieved with
2374 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002375 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002376 conn = Connection(Context(TLSv1_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002377 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002378 app_data = object()
2379 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002380 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002381
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002382 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002383 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002384 :py:obj:`Connection.makefile` is not implemented and calling that
2385 method raises :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002386 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002387 conn = Connection(Context(TLSv1_METHOD), None)
2388 self.assertRaises(NotImplementedError, conn.makefile)
2389
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002390 def test_get_peer_cert_chain_wrong_args(self):
2391 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002392 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if
2393 called with any arguments.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002394 """
2395 conn = Connection(Context(TLSv1_METHOD), None)
2396 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
2397 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
2398 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
2399 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
2400
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002401 def test_get_peer_cert_chain(self):
2402 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002403 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates
2404 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002405 """
2406 chain = _create_certificate_chain()
2407 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2408
2409 serverContext = Context(TLSv1_METHOD)
2410 serverContext.use_privatekey(skey)
2411 serverContext.use_certificate(scert)
2412 serverContext.add_extra_chain_cert(icert)
2413 serverContext.add_extra_chain_cert(cacert)
2414 server = Connection(serverContext, None)
2415 server.set_accept_state()
2416
2417 # Create the client
2418 clientContext = Context(TLSv1_METHOD)
2419 clientContext.set_verify(VERIFY_NONE, verify_cb)
2420 client = Connection(clientContext, None)
2421 client.set_connect_state()
2422
2423 self._interactInMemory(client, server)
2424
2425 chain = client.get_peer_cert_chain()
2426 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002427 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002428 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002429 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002430 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002431 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002432 "Authority Certificate", chain[2].get_subject().CN)
2433
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002434 def test_get_peer_cert_chain_none(self):
2435 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002436 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the
2437 peer sends no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002438 """
2439 ctx = Context(TLSv1_METHOD)
2440 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2441 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2442 server = Connection(ctx, None)
2443 server.set_accept_state()
2444 client = Connection(Context(TLSv1_METHOD), None)
2445 client.set_connect_state()
2446 self._interactInMemory(client, server)
2447 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002448
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002449 def test_get_session_wrong_args(self):
2450 """
2451 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
2452 with any arguments.
2453 """
2454 ctx = Context(TLSv1_METHOD)
2455 server = Connection(ctx, None)
2456 self.assertRaises(TypeError, server.get_session, 123)
2457 self.assertRaises(TypeError, server.get_session, "hello")
2458 self.assertRaises(TypeError, server.get_session, object())
2459
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002460 def test_get_session_unconnected(self):
2461 """
2462 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
2463 an object which has not been connected.
2464 """
2465 ctx = Context(TLSv1_METHOD)
2466 server = Connection(ctx, None)
2467 session = server.get_session()
2468 self.assertIdentical(None, session)
2469
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002470 def test_server_get_session(self):
2471 """
2472 On the server side of a connection, :py:obj:`Connection.get_session`
2473 returns a :py:class:`Session` instance representing the SSL session for
2474 that connection.
2475 """
2476 server, client = self._loopback()
2477 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002478 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002479
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002480 def test_client_get_session(self):
2481 """
2482 On the client side of a connection, :py:obj:`Connection.get_session`
2483 returns a :py:class:`Session` instance representing the SSL session for
2484 that connection.
2485 """
2486 server, client = self._loopback()
2487 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002488 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002489
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002490 def test_set_session_wrong_args(self):
2491 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002492 If called with an object that is not an instance of
2493 :py:class:`Session`, or with other than one argument,
2494 :py:obj:`Connection.set_session` raises :py:obj:`TypeError`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002495 """
2496 ctx = Context(TLSv1_METHOD)
2497 connection = Connection(ctx, None)
2498 self.assertRaises(TypeError, connection.set_session)
2499 self.assertRaises(TypeError, connection.set_session, 123)
2500 self.assertRaises(TypeError, connection.set_session, "hello")
2501 self.assertRaises(TypeError, connection.set_session, object())
2502 self.assertRaises(
2503 TypeError, connection.set_session, Session(), Session())
2504
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002505 def test_client_set_session(self):
2506 """
2507 :py:obj:`Connection.set_session`, when used prior to a connection being
2508 established, accepts a :py:class:`Session` instance and causes an
2509 attempt to re-use the session it represents when the SSL handshake is
2510 performed.
2511 """
2512 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2513 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2514 ctx = Context(TLSv1_METHOD)
2515 ctx.use_privatekey(key)
2516 ctx.use_certificate(cert)
2517 ctx.set_session_id("unity-test")
2518
2519 def makeServer(socket):
2520 server = Connection(ctx, socket)
2521 server.set_accept_state()
2522 return server
2523
2524 originalServer, originalClient = self._loopback(
2525 serverFactory=makeServer)
2526 originalSession = originalClient.get_session()
2527
2528 def makeClient(socket):
2529 client = self._loopbackClientFactory(socket)
2530 client.set_session(originalSession)
2531 return client
2532 resumedServer, resumedClient = self._loopback(
2533 serverFactory=makeServer,
2534 clientFactory=makeClient)
2535
2536 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002537 # identifier for the session (new enough versions of OpenSSL expose
2538 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002539 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002540 # session is re-used. As long as the master key for the two
2541 # connections is the same, the session was re-used!
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002542 self.assertEqual(
2543 originalServer.master_key(), resumedServer.master_key())
2544
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002545 def test_set_session_wrong_method(self):
2546 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002547 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002548 instance associated with a context using a different SSL method than
2549 the :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002550 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002551 """
2552 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2553 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2554 ctx = Context(TLSv1_METHOD)
2555 ctx.use_privatekey(key)
2556 ctx.use_certificate(cert)
2557 ctx.set_session_id("unity-test")
2558
2559 def makeServer(socket):
2560 server = Connection(ctx, socket)
2561 server.set_accept_state()
2562 return server
2563
2564 originalServer, originalClient = self._loopback(
2565 serverFactory=makeServer)
2566 originalSession = originalClient.get_session()
2567
2568 def makeClient(socket):
2569 # Intentionally use a different, incompatible method here.
2570 client = Connection(Context(SSLv3_METHOD), socket)
2571 client.set_connect_state()
2572 client.set_session(originalSession)
2573 return client
2574
2575 self.assertRaises(
2576 Error,
2577 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2578
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002579 def test_wantWriteError(self):
2580 """
2581 :py:obj:`Connection` methods which generate output raise
2582 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2583 fail indicating a should-write state.
2584 """
2585 client_socket, server_socket = socket_pair()
2586 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002587 # anything. Only write a single byte at a time so we can be sure we
2588 # completely fill the buffer. Even though the socket API is allowed to
2589 # signal a short write via its return value it seems this doesn't
2590 # always happen on all platforms (FreeBSD and OS X particular) for the
2591 # very last bit of available buffer space.
2592 msg = b"x"
2593 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002594 try:
2595 client_socket.send(msg)
2596 except error as e:
2597 if e.errno == EWOULDBLOCK:
2598 break
2599 raise
2600 else:
2601 self.fail(
2602 "Failed to fill socket buffer, cannot test BIO want write")
2603
2604 ctx = Context(TLSv1_METHOD)
2605 conn = Connection(ctx, client_socket)
2606 # Client's speak first, so make it an SSL client
2607 conn.set_connect_state()
2608 self.assertRaises(WantWriteError, conn.do_handshake)
2609
2610 # XXX want_read
2611
Fedor Brunner416f4a12014-03-28 13:18:38 +01002612 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002613 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002614 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2615 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002616 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002617 ctx = Context(TLSv1_METHOD)
2618 connection = Connection(ctx, None)
2619 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002620
2621 def test_get_peer_finished_before_connect(self):
2622 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002623 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2624 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002625 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002626 ctx = Context(TLSv1_METHOD)
2627 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002628 self.assertEqual(connection.get_peer_finished(), None)
2629
Fedor Brunner416f4a12014-03-28 13:18:38 +01002630 def test_get_finished(self):
2631 """
2632 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002633 message send from client, or server. Finished messages are send during
2634 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002635 """
2636
Fedor Brunner5747b932014-03-05 14:22:34 +01002637 server, client = self._loopback()
2638
2639 self.assertNotEqual(server.get_finished(), None)
2640 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002641
2642 def test_get_peer_finished(self):
2643 """
2644 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002645 message received from client, or server. Finished messages are send
2646 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002647 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002648 server, client = self._loopback()
2649
2650 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002651 self.assertTrue(len(server.get_peer_finished()) > 0)
2652
Fedor Brunner416f4a12014-03-28 13:18:38 +01002653 def test_tls_finished_message_symmetry(self):
2654 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002655 The TLS Finished message send by server must be the TLS Finished
2656 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002657
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002658 The TLS Finished message send by client must be the TLS Finished
2659 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002660 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002661 server, client = self._loopback()
2662
Fedor Brunner5747b932014-03-05 14:22:34 +01002663 self.assertEqual(server.get_finished(), client.get_peer_finished())
2664 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002665
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002666 def test_get_cipher_name_before_connect(self):
2667 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002668 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2669 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002670 """
2671 ctx = Context(TLSv1_METHOD)
2672 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002673 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002674
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002675 def test_get_cipher_name(self):
2676 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002677 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2678 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002679 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002680 server, client = self._loopback()
2681 server_cipher_name, client_cipher_name = \
2682 server.get_cipher_name(), client.get_cipher_name()
2683
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002684 self.assertIsInstance(server_cipher_name, text_type)
2685 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002686
2687 self.assertEqual(server_cipher_name, client_cipher_name)
2688
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002689 def test_get_cipher_version_before_connect(self):
2690 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002691 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2692 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002693 """
2694 ctx = Context(TLSv1_METHOD)
2695 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002696 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002697
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002698 def test_get_cipher_version(self):
2699 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002700 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2701 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002702 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002703 server, client = self._loopback()
2704 server_cipher_version, client_cipher_version = \
2705 server.get_cipher_version(), client.get_cipher_version()
2706
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002707 self.assertIsInstance(server_cipher_version, text_type)
2708 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002709
2710 self.assertEqual(server_cipher_version, client_cipher_version)
2711
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002712 def test_get_cipher_bits_before_connect(self):
2713 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002714 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2715 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002716 """
2717 ctx = Context(TLSv1_METHOD)
2718 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002719 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002720
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002721 def test_get_cipher_bits(self):
2722 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002723 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2724 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002725 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002726 server, client = self._loopback()
2727 server_cipher_bits, client_cipher_bits = \
2728 server.get_cipher_bits(), client.get_cipher_bits()
2729
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002730 self.assertIsInstance(server_cipher_bits, int)
2731 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002732
2733 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002734
Jim Shaverabff1882015-05-27 09:15:55 -04002735 def test_get_protocol_version_name(self):
2736 """
2737 :py:obj:`Connection.get_protocol_version_name()` returns a string
2738 giving the protocol version of the current connection.
2739 """
2740 server, client = self._loopback()
2741 client_protocol_version_name = client.get_protocol_version_name()
2742 server_protocol_version_name = server.get_protocol_version_name()
2743
Jim Shaver58d25732015-05-28 11:52:32 -04002744 self.assertIsInstance(server_protocol_version_name, text_type)
2745 self.assertIsInstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002746
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002747 self.assertEqual(
2748 server_protocol_version_name, client_protocol_version_name
2749 )
Jim Shaverabff1882015-05-27 09:15:55 -04002750
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002751 def test_get_protocol_version(self):
2752 """
Alex Gaynor43307782015-09-04 09:05:45 -04002753 :py:obj:`Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002754 giving the protocol version of the current connection.
2755 """
2756 server, client = self._loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002757 client_protocol_version = client.get_protocol_version()
2758 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002759
Jim Shaverabff1882015-05-27 09:15:55 -04002760 self.assertIsInstance(server_protocol_version, int)
2761 self.assertIsInstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002762
2763 self.assertEqual(server_protocol_version, client_protocol_version)
2764
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002765
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002766class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002767 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002768 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002769 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002770 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002771 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002772 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if
2773 called with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002774 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002775 connection = Connection(Context(TLSv1_METHOD), None)
2776 self.assertRaises(TypeError, connection.get_cipher_list, None)
2777
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002778 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002779 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002780 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2781 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002782 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002783 connection = Connection(Context(TLSv1_METHOD), None)
2784 ciphers = connection.get_cipher_list()
2785 self.assertTrue(isinstance(ciphers, list))
2786 for cipher in ciphers:
2787 self.assertTrue(isinstance(cipher, str))
2788
2789
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002790class ConnectionSendTests(TestCase, _LoopbackMixin):
2791 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002792 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002793 """
2794 def test_wrong_args(self):
2795 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002796 When called with arguments other than string argument for its first
2797 parameter or more than two arguments, :py:obj:`Connection.send` raises
2798 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002799 """
2800 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002801 self.assertRaises(TypeError, connection.send)
2802 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002803 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002804
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002805 def test_short_bytes(self):
2806 """
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002807 When passed a short byte string, :py:obj:`Connection.send` transmits
2808 all of it and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002809 """
2810 server, client = self._loopback()
2811 count = server.send(b('xy'))
2812 self.assertEquals(count, 2)
2813 self.assertEquals(client.recv(2), b('xy'))
2814
Abraham Martinef063482015-03-25 14:06:24 +00002815 def test_text(self):
2816 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002817 When passed a text, :py:obj:`Connection.send` transmits all of it and
2818 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002819 """
2820 server, client = self._loopback()
2821 with catch_warnings(record=True) as w:
2822 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002823 count = server.send(b"xy".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002824 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002825 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002826 WARNING_TYPE_EXPECTED
2827 ),
2828 str(w[-1].message)
2829 )
2830 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinef063482015-03-25 14:06:24 +00002831 self.assertEquals(count, 2)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002832 self.assertEquals(client.recv(2), b"xy")
Abraham Martinef063482015-03-25 14:06:24 +00002833
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002834 @skip_if_py26
2835 def test_short_memoryview(self):
2836 """
2837 When passed a memoryview onto a small number of bytes,
2838 :py:obj:`Connection.send` transmits all of them and returns the number
2839 of bytes sent.
2840 """
2841 server, client = self._loopback()
2842 count = server.send(memoryview(b('xy')))
2843 self.assertEquals(count, 2)
2844 self.assertEquals(client.recv(2), b('xy'))
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002845
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02002846 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002847 def test_short_buffer(self):
2848 """
2849 When passed a buffer containing a small number of bytes,
2850 :py:obj:`Connection.send` transmits all of them and returns the number
2851 of bytes sent.
2852 """
2853 server, client = self._loopback()
2854 count = server.send(buffer(b('xy')))
2855 self.assertEquals(count, 2)
2856 self.assertEquals(client.recv(2), b('xy'))
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002857
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002858
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002859def _make_memoryview(size):
2860 """
2861 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2862 size.
2863 """
2864 return memoryview(bytearray(size))
2865
2866
Cory Benfield62d10332014-06-15 10:03:41 +01002867class ConnectionRecvIntoTests(TestCase, _LoopbackMixin):
2868 """
2869 Tests for :py:obj:`Connection.recv_into`
2870 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002871 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002872 """
2873 Assert that when the given buffer is passed to
2874 ``Connection.recv_into``, whatever bytes are available to be received
2875 that fit into that buffer are written into that buffer.
2876 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002877 output_buffer = factory(5)
2878
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002879 server, client = self._loopback()
2880 server.send(b('xy'))
2881
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002882 self.assertEqual(client.recv_into(output_buffer), 2)
2883 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002884
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002885 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002886 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002887 :py:obj:`Connection.recv_into` can be passed a ``bytearray`` instance
2888 and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002889 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002890 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002891
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002892 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002893 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002894 Assert that when the given buffer is passed to ``Connection.recv_into``
2895 along with a value for ``nbytes`` that is less than the size of that
2896 buffer, only ``nbytes`` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002897 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002898 output_buffer = factory(10)
2899
Cory Benfield62d10332014-06-15 10:03:41 +01002900 server, client = self._loopback()
2901 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002902
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002903 self.assertEqual(client.recv_into(output_buffer, 5), 5)
2904 self.assertEqual(
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002905 output_buffer, bytearray(b('abcde\x00\x00\x00\x00\x00'))
2906 )
2907
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002908 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002909 """
2910 When called with a ``bytearray`` instance,
2911 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter and
2912 doesn't copy in more than that number of bytes.
2913 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002914 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002915
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002916 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002917 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002918 Assert that if there are more bytes available to be read from the
2919 receive buffer than would fit into the buffer passed to
2920 :py:obj:`Connection.recv_into`, only as many as fit are written into
2921 it.
Cory Benfield62d10332014-06-15 10:03:41 +01002922 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002923 output_buffer = factory(5)
2924
Cory Benfield62d10332014-06-15 10:03:41 +01002925 server, client = self._loopback()
2926 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002927
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002928 self.assertEqual(client.recv_into(output_buffer), 5)
2929 self.assertEqual(output_buffer, bytearray(b('abcde')))
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002930 rest = client.recv(5)
2931 self.assertEqual(b('fghij'), rest)
2932
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002933 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002934 """
2935 When called with a ``bytearray`` instance,
2936 :py:obj:`Connection.recv_into` respects the size of the array and
2937 doesn't write more bytes into it than will fit.
2938 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002939 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002940
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002941 def _really_doesnt_overfill_test(self, factory):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002942 """
2943 Assert that if the value given by ``nbytes`` is greater than the actual
2944 size of the output buffer passed to :py:obj:`Connection.recv_into`, the
2945 behavior is as if no value was given for ``nbytes`` at all.
2946 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002947 output_buffer = factory(5)
2948
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002949 server, client = self._loopback()
2950 server.send(b('abcdefghij'))
2951
2952 self.assertEqual(client.recv_into(output_buffer, 50), 5)
2953 self.assertEqual(output_buffer, bytearray(b('abcde')))
2954 rest = client.recv(5)
2955 self.assertEqual(b('fghij'), rest)
2956
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002957 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002958 """
2959 When called with a ``bytearray`` instance and an ``nbytes`` value that
2960 is too large, :py:obj:`Connection.recv_into` respects the size of the
2961 array and not the ``nbytes`` value and doesn't write more bytes into
2962 the buffer than will fit.
2963 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002964 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002965
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002966 def test_peek(self):
2967
2968 server, client = self._loopback()
2969 server.send(b('xy'))
2970
2971 for _ in range(2):
2972 output_buffer = bytearray(5)
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002973 self.assertEqual(
2974 client.recv_into(output_buffer, flags=MSG_PEEK), 2)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002975 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
2976
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002977 @skip_if_py26
2978 def test_memoryview_no_length(self):
2979 """
2980 :py:obj:`Connection.recv_into` can be passed a ``memoryview``
2981 instance and data in the receive buffer is written to it.
2982 """
2983 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002984
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002985 @skip_if_py26
2986 def test_memoryview_respects_length(self):
2987 """
2988 When called with a ``memoryview`` instance,
2989 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter
2990 and doesn't copy more than that number of bytes in.
2991 """
2992 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002993
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002994 @skip_if_py26
2995 def test_memoryview_doesnt_overfill(self):
2996 """
2997 When called with a ``memoryview`` instance,
2998 :py:obj:`Connection.recv_into` respects the size of the array and
2999 doesn't write more bytes into it than will fit.
3000 """
3001 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003002
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003003 @skip_if_py26
3004 def test_memoryview_really_doesnt_overfill(self):
3005 """
3006 When called with a ``memoryview`` instance and an ``nbytes`` value
3007 that is too large, :py:obj:`Connection.recv_into` respects the size
3008 of the array and not the ``nbytes`` value and doesn't write more
3009 bytes into the buffer than will fit.
3010 """
3011 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003012
Cory Benfield62d10332014-06-15 10:03:41 +01003013
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003014class ConnectionSendallTests(TestCase, _LoopbackMixin):
3015 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003016 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003017 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003018 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003019 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003020 When called with arguments other than a string argument for its first
3021 parameter or with more than two arguments, :py:obj:`Connection.sendall`
3022 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003023 """
3024 connection = Connection(Context(TLSv1_METHOD), None)
3025 self.assertRaises(TypeError, connection.sendall)
3026 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003027 self.assertRaises(
3028 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003029
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003030 def test_short(self):
3031 """
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003032 :py:obj:`Connection.sendall` transmits all of the bytes in the string
3033 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003034 """
3035 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04003036 server.sendall(b('x'))
3037 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003038
Abraham Martinef063482015-03-25 14:06:24 +00003039 def test_text(self):
3040 """
Jean-Paul Calderone93477422015-04-13 20:38:57 -04003041 :py:obj:`Connection.sendall` transmits all the content in the string
3042 passed to it raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003043 """
3044 server, client = self._loopback()
3045 with catch_warnings(record=True) as w:
3046 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003047 server.sendall(b"x".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003048 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003049 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003050 WARNING_TYPE_EXPECTED
3051 ),
3052 str(w[-1].message)
3053 )
3054 self.assertIs(w[-1].category, DeprecationWarning)
3055 self.assertEquals(client.recv(1), b"x")
Abraham Martinef063482015-03-25 14:06:24 +00003056
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003057 @skip_if_py26
3058 def test_short_memoryview(self):
3059 """
3060 When passed a memoryview onto a small number of bytes,
3061 :py:obj:`Connection.sendall` transmits all of them.
3062 """
3063 server, client = self._loopback()
3064 server.sendall(memoryview(b('x')))
3065 self.assertEquals(client.recv(1), b('x'))
Abraham Martinef063482015-03-25 14:06:24 +00003066
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003067 @skip_if_py3
3068 def test_short_buffers(self):
3069 """
3070 When passed a buffer containing a small number of bytes,
3071 :py:obj:`Connection.sendall` transmits all of them.
3072 """
3073 server, client = self._loopback()
3074 server.sendall(buffer(b('x')))
3075 self.assertEquals(client.recv(1), b('x'))
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003076
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003077 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003078 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003079 :py:obj:`Connection.sendall` transmits all of the bytes in the string
3080 passed to it even if this requires multiple calls of an underlying
3081 write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003082 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003083 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003084 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003085 # On Windows, after 32k of bytes the write will block (forever
3086 # - because no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04003087 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003088 server.sendall(message)
3089 accum = []
3090 received = 0
3091 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003092 data = client.recv(1024)
3093 accum.append(data)
3094 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04003095 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003096
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003097 def test_closed(self):
3098 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003099 If the underlying socket is closed, :py:obj:`Connection.sendall`
3100 propagates the write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003101 """
3102 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003103 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003104 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003105 if platform == "win32":
3106 self.assertEqual(exc.args[0], ESHUTDOWN)
3107 else:
3108 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003109
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003110
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003111class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
3112 """
3113 Tests for SSL renegotiation APIs.
3114 """
3115 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003116 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003117 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called
3118 with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003119 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003120 connection = Connection(Context(TLSv1_METHOD), None)
3121 self.assertRaises(TypeError, connection.renegotiate, None)
3122
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003123 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003124 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003125 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if
3126 called with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003127 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003128 connection = Connection(Context(TLSv1_METHOD), None)
3129 self.assertRaises(TypeError, connection.total_renegotiations, None)
3130
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003131 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003132 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003133 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before
3134 any renegotiations have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003135 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003136 connection = Connection(Context(TLSv1_METHOD), None)
3137 self.assertEquals(connection.total_renegotiations(), 0)
3138
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003139# def test_renegotiate(self):
3140# """
3141# """
3142# server, client = self._loopback()
3143
3144# server.send("hello world")
3145# self.assertEquals(client.recv(len("hello world")), "hello world")
3146
3147# self.assertEquals(server.total_renegotiations(), 0)
3148# self.assertTrue(server.renegotiate())
3149
3150# server.setblocking(False)
3151# client.setblocking(False)
3152# while server.renegotiate_pending():
3153# client.do_handshake()
3154# server.do_handshake()
3155
3156# self.assertEquals(server.total_renegotiations(), 1)
3157
3158
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003159class ErrorTests(TestCase):
3160 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003161 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003162 """
3163 def test_type(self):
3164 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003165 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003166 """
3167 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05003168 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05003169
3170
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003171class ConstantsTests(TestCase):
3172 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003173 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003174
3175 These are values defined by OpenSSL intended only to be used as flags to
3176 OpenSSL APIs. The only assertions it seems can be made about them is
3177 their values.
3178 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003179 @pytest.mark.skipif(
3180 OP_NO_QUERY_MTU is None,
3181 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
3182 )
3183 def test_op_no_query_mtu(self):
3184 """
3185 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3186 of :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
3187 """
3188 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003189
Hynek Schlawack35618382015-09-05 21:54:25 +02003190 @pytest.mark.skipif(
3191 OP_COOKIE_EXCHANGE is None,
3192 reason="OP_COOKIE_EXCHANGE unavailable - "
3193 "OpenSSL version may be too old"
3194 )
3195 def test_op_cookie_exchange(self):
3196 """
3197 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3198 value of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by
3199 :file:`openssl/ssl.h`.
3200 """
3201 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003202
Hynek Schlawack35618382015-09-05 21:54:25 +02003203 @pytest.mark.skipif(
3204 OP_NO_TICKET is None,
3205 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old"
3206 )
3207 def test_op_no_ticket(self):
3208 """
3209 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3210 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
3211 """
3212 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003213
Hynek Schlawack35618382015-09-05 21:54:25 +02003214 @pytest.mark.skipif(
3215 OP_NO_COMPRESSION is None,
3216 reason="OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3217 )
3218 def test_op_no_compression(self):
3219 """
3220 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3221 value of :py:const:`SSL_OP_NO_COMPRESSION` defined by
3222 :file:`openssl/ssl.h`.
3223 """
3224 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003225
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003226 def test_sess_cache_off(self):
3227 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003228 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3229 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003230 """
3231 self.assertEqual(0x0, SESS_CACHE_OFF)
3232
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003233 def test_sess_cache_client(self):
3234 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003235 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3236 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003237 """
3238 self.assertEqual(0x1, SESS_CACHE_CLIENT)
3239
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003240 def test_sess_cache_server(self):
3241 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003242 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3243 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003244 """
3245 self.assertEqual(0x2, SESS_CACHE_SERVER)
3246
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003247 def test_sess_cache_both(self):
3248 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003249 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3250 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003251 """
3252 self.assertEqual(0x3, SESS_CACHE_BOTH)
3253
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003254 def test_sess_cache_no_auto_clear(self):
3255 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003256 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3257 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3258 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003259 """
3260 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
3261
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003262 def test_sess_cache_no_internal_lookup(self):
3263 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003264 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3265 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3266 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003267 """
3268 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
3269
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003270 def test_sess_cache_no_internal_store(self):
3271 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003272 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3273 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3274 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003275 """
3276 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
3277
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003278 def test_sess_cache_no_internal(self):
3279 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003280 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3281 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
3282 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003283 """
3284 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
3285
3286
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003287class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05003288 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003289 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003290 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003291 def _server(self, sock):
3292 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003293 Create a new server-side SSL :py:obj:`Connection` object wrapped around
3294 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003295 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003296 # Create the server side Connection. This is mostly setup boilerplate
3297 # - use TLSv1, use a particular certificate, etc.
3298 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003299 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003300 server_ctx.set_verify(
3301 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3302 verify_cb
3303 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003304 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003305 server_ctx.use_privatekey(
3306 load_privatekey(FILETYPE_PEM, server_key_pem))
3307 server_ctx.use_certificate(
3308 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003309 server_ctx.check_privatekey()
3310 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003311 # Here the Connection is actually created. If None is passed as the
3312 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003313 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003314 server_conn.set_accept_state()
3315 return server_conn
3316
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003317 def _client(self, sock):
3318 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003319 Create a new client-side SSL :py:obj:`Connection` object wrapped around
3320 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003321 """
3322 # Now create the client side Connection. Similar boilerplate to the
3323 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003324 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003325 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003326 client_ctx.set_verify(
3327 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3328 verify_cb
3329 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003330 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003331 client_ctx.use_privatekey(
3332 load_privatekey(FILETYPE_PEM, client_key_pem))
3333 client_ctx.use_certificate(
3334 load_certificate(FILETYPE_PEM, client_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003335 client_ctx.check_privatekey()
3336 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003337 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003338 client_conn.set_connect_state()
3339 return client_conn
3340
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003341 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003342 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003343 Two :py:obj:`Connection`s which use memory BIOs can be manually
3344 connected by reading from the output of each and writing those bytes to
3345 the input of the other and in this way establish a connection and
3346 exchange application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003347 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003348 server_conn = self._server(None)
3349 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003350
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003351 # There should be no key or nonces yet.
3352 self.assertIdentical(server_conn.master_key(), None)
3353 self.assertIdentical(server_conn.client_random(), None)
3354 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003355
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003356 # First, the handshake needs to happen. We'll deliver bytes back and
3357 # forth between the client and server until neither of them feels like
3358 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003359 self.assertIdentical(
3360 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003361
3362 # Now that the handshake is done, there should be a key and nonces.
3363 self.assertNotIdentical(server_conn.master_key(), None)
3364 self.assertNotIdentical(server_conn.client_random(), None)
3365 self.assertNotIdentical(server_conn.server_random(), None)
Hynek Schlawack35618382015-09-05 21:54:25 +02003366 self.assertEquals(
3367 server_conn.client_random(), client_conn.client_random())
3368 self.assertEquals(
3369 server_conn.server_random(), client_conn.server_random())
3370 self.assertNotEquals(
3371 server_conn.client_random(), server_conn.server_random())
3372 self.assertNotEquals(
3373 client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003374
3375 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003376 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05003377
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003378 server_conn.write(important_message)
3379 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003380 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003381 (client_conn, important_message))
3382
3383 client_conn.write(important_message[::-1])
3384 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003385 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003386 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003387
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003388 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003389 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003390 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003391
Hynek Schlawack35618382015-09-05 21:54:25 +02003392 This is primarily to rule out the memory BIO code as the source of any
3393 problems encountered while passing data over a :py:obj:`Connection` (if
3394 this test fails, there must be a problem outside the memory BIO code,
3395 as no memory BIO is involved here). Even though this isn't a memory
3396 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003397 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04003398 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003399
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003400 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05003401 client_conn.send(important_message)
3402 msg = server_conn.recv(1024)
3403 self.assertEqual(msg, important_message)
3404
3405 # Again in the other direction, just for fun.
3406 important_message = important_message[::-1]
3407 server_conn.send(important_message)
3408 msg = client_conn.recv(1024)
3409 self.assertEqual(msg, important_message)
3410
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04003411 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003412 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003413 Test that :py:obj:`OpenSSL.SSL.bio_read` and
3414 :py:obj:`OpenSSL.SSL.bio_write` don't work on
3415 :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003416 """
3417 context = Context(SSLv3_METHOD)
3418 client = socket()
3419 clientSSL = Connection(context, client)
Alex Gaynor43307782015-09-04 09:05:45 -04003420 self.assertRaises(TypeError, clientSSL.bio_read, 100)
3421 self.assertRaises(TypeError, clientSSL.bio_write, "foo")
Alex Gaynor7e8b61e2015-09-04 13:13:05 -04003422 self.assertRaises(TypeError, clientSSL.bio_shutdown)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003423
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003424 def test_outgoingOverflow(self):
3425 """
3426 If more bytes than can be written to the memory BIO are passed to
Hynek Schlawack35618382015-09-05 21:54:25 +02003427 :py:obj:`Connection.send` at once, the number of bytes which were
3428 written is returned and that many bytes from the beginning of the input
3429 can be read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003430 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003431 server = self._server(None)
3432 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003433
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003434 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003435
3436 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003437 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003438 # Sanity check. We're trying to test what happens when the entire
3439 # input can't be sent. If the entire input was sent, this test is
3440 # meaningless.
3441 self.assertTrue(sent < size)
3442
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003443 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003444 self.assertIdentical(receiver, server)
3445
3446 # We can rely on all of these bytes being received at once because
3447 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
3448 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003449
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003450 def test_shutdown(self):
3451 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003452 :py:obj:`Connection.bio_shutdown` signals the end of the data stream
3453 from which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003454 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003455 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003456 server.bio_shutdown()
3457 e = self.assertRaises(Error, server.recv, 1024)
3458 # We don't want WantReadError or ZeroReturnError or anything - it's a
3459 # handshake failure.
3460 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003461
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003462 def test_unexpectedEndOfFile(self):
3463 """
3464 If the connection is lost before an orderly SSL shutdown occurs,
3465 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
3466 "Unexpected EOF".
3467 """
3468 server_conn, client_conn = self._loopback()
3469 client_conn.sock_shutdown(SHUT_RDWR)
3470 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
3471 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
3472
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003473 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003474 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003475 Verify the return value of the :py:obj:`get_client_ca_list` method for
3476 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003477
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003478 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003479 before the client and server are connected to each other. This
3480 function should specify a list of CAs for the server to send to the
3481 client and return that same list. The list will be used to verify
Hynek Schlawack35618382015-09-05 21:54:25 +02003482 that :py:obj:`get_client_ca_list` returns the proper value at
3483 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003484 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003485 server = self._server(None)
3486 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003487 self.assertEqual(client.get_client_ca_list(), [])
3488 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003489 ctx = server.get_context()
3490 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003491 self.assertEqual(client.get_client_ca_list(), [])
3492 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003493 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003494 self.assertEqual(client.get_client_ca_list(), expected)
3495 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003496
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003497 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003498 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003499 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if
3500 called with a non-list or a list that contains objects other than
3501 X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003502 """
3503 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003504 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
3505 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
3506 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003507
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003508 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003509 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003510 If passed an empty list, :py:obj:`Context.set_client_ca_list`
3511 configures the context to send no CA names to the client and, on both
3512 the server and client sides, :py:obj:`Connection.get_client_ca_list`
3513 returns an empty list after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003514 """
3515 def no_ca(ctx):
3516 ctx.set_client_ca_list([])
3517 return []
3518 self._check_client_ca_list(no_ca)
3519
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003520 def test_set_one_ca_list(self):
3521 """
3522 If passed a list containing a single X509Name,
Hynek Schlawack35618382015-09-05 21:54:25 +02003523 :py:obj:`Context.set_client_ca_list` configures the context to send
3524 that CA name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003525 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003526 X509Name after the connection is set up.
3527 """
3528 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3529 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003530
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003531 def single_ca(ctx):
3532 ctx.set_client_ca_list([cadesc])
3533 return [cadesc]
3534 self._check_client_ca_list(single_ca)
3535
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003536 def test_set_multiple_ca_list(self):
3537 """
3538 If passed a list containing multiple X509Name objects,
Hynek Schlawack35618382015-09-05 21:54:25 +02003539 :py:obj:`Context.set_client_ca_list` configures the context to send
3540 those CA names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003541 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003542 X509Names after the connection is set up.
3543 """
3544 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3545 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3546
3547 sedesc = secert.get_subject()
3548 cldesc = clcert.get_subject()
3549
3550 def multiple_ca(ctx):
3551 L = [sedesc, cldesc]
3552 ctx.set_client_ca_list(L)
3553 return L
3554 self._check_client_ca_list(multiple_ca)
3555
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003556 def test_reset_ca_list(self):
3557 """
3558 If called multiple times, only the X509Names passed to the final call
Hynek Schlawack35618382015-09-05 21:54:25 +02003559 of :py:obj:`Context.set_client_ca_list` are used to configure the CA
3560 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003561 """
3562 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3563 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3564 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3565
3566 cadesc = cacert.get_subject()
3567 sedesc = secert.get_subject()
3568 cldesc = clcert.get_subject()
3569
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003570 def changed_ca(ctx):
3571 ctx.set_client_ca_list([sedesc, cldesc])
3572 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003573 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003574 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003575
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003576 def test_mutated_ca_list(self):
3577 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003578 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003579 afterwards, this does not affect the list of CA names sent to the
3580 client.
3581 """
3582 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3583 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3584
3585 cadesc = cacert.get_subject()
3586 sedesc = secert.get_subject()
3587
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003588 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003589 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003590 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003591 L.append(sedesc)
3592 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003593 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003594
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003595 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003596 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003597 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called
3598 with a non-X509 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003599 """
3600 ctx = Context(TLSv1_METHOD)
3601 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003602 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003603 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003604 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003605
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003606 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003607 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003608 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09003609 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003610 """
3611 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3612 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003613
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003614 def single_ca(ctx):
3615 ctx.add_client_ca(cacert)
3616 return [cadesc]
3617 self._check_client_ca_list(single_ca)
3618
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003619 def test_multiple_add_client_ca(self):
3620 """
3621 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09003622 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003623 """
3624 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3625 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3626
3627 cadesc = cacert.get_subject()
3628 sedesc = secert.get_subject()
3629
3630 def multiple_ca(ctx):
3631 ctx.add_client_ca(cacert)
3632 ctx.add_client_ca(secert)
3633 return [cadesc, sedesc]
3634 self._check_client_ca_list(multiple_ca)
3635
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003636 def test_set_and_add_client_ca(self):
3637 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003638 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
Hynek Schlawack35618382015-09-05 21:54:25 +02003639 :py:obj:`Context.add_client_ca` results in using the CA names from the
3640 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003641 """
3642 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3643 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3644 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3645
3646 cadesc = cacert.get_subject()
3647 sedesc = secert.get_subject()
3648 cldesc = clcert.get_subject()
3649
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003650 def mixed_set_add_ca(ctx):
3651 ctx.set_client_ca_list([cadesc, sedesc])
3652 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003653 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003654 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003655
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003656 def test_set_after_add_client_ca(self):
3657 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003658 A call to :py:obj:`Context.set_client_ca_list` after a call to
Hynek Schlawack35618382015-09-05 21:54:25 +02003659 :py:obj:`Context.add_client_ca` replaces the CA name specified by the
3660 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003661 """
3662 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3663 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3664 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3665
3666 cadesc = cacert.get_subject()
3667 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003668
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003669 def set_replaces_add_ca(ctx):
3670 ctx.add_client_ca(clcert)
3671 ctx.set_client_ca_list([cadesc])
3672 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003673 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003674 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003675
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003676
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003677class ConnectionBIOTests(TestCase):
3678 """
3679 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3680 """
3681 def test_wantReadError(self):
3682 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003683 :py:obj:`Connection.bio_read` raises
3684 :py:obj:`OpenSSL.SSL.WantReadError` if there are no bytes available to
3685 be read from the BIO.
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003686 """
3687 ctx = Context(TLSv1_METHOD)
3688 conn = Connection(ctx, None)
3689 self.assertRaises(WantReadError, conn.bio_read, 1024)
3690
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003691 def test_buffer_size(self):
3692 """
3693 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3694 number of bytes to read and return.
3695 """
3696 ctx = Context(TLSv1_METHOD)
3697 conn = Connection(ctx, None)
3698 conn.set_connect_state()
3699 try:
3700 conn.do_handshake()
3701 except WantReadError:
3702 pass
3703 data = conn.bio_read(2)
3704 self.assertEqual(2, len(data))
3705
Hynek Schlawack35618382015-09-05 21:54:25 +02003706 @skip_if_py3
3707 def test_buffer_size_long(self):
3708 """
3709 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3710 :py:obj:`long` as well as :py:obj:`int`.
3711 """
3712 ctx = Context(TLSv1_METHOD)
3713 conn = Connection(ctx, None)
3714 conn.set_connect_state()
3715 try:
3716 conn.do_handshake()
3717 except WantReadError:
3718 pass
3719 data = conn.bio_read(long(2))
3720 self.assertEqual(2, len(data))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003721
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003722
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003723class InfoConstantTests(TestCase):
3724 """
3725 Tests for assorted constants exposed for use in info callbacks.
3726 """
3727 def test_integers(self):
3728 """
3729 All of the info constants are integers.
3730
3731 This is a very weak test. It would be nice to have one that actually
3732 verifies that as certain info events happen, the value passed to the
3733 info callback matches up with the constant exposed by OpenSSL.SSL.
3734 """
3735 for const in [
3736 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3737 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3738 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3739 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3740 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
Hynek Schlawack35618382015-09-05 21:54:25 +02003741 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE
3742 ]:
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003743 self.assertTrue(isinstance(const, int))
3744
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003745
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003746if __name__ == '__main__':
3747 main()