blob: 4a23ef7d559b0704288e63cbb5930f17e84bbb0a [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"""
Jonathan Ballet648875f2011-07-16 14:14:58 +09005Unit tests for :py:obj:`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
Jean-Paul Calderone516c12c2015-04-13 20:34:57 -040010from sys import platform, getfilesystemencoding
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
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -040020from six import PY3, text_type, u
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 Calderone17eca482015-04-13 20:31:07 -040050from OpenSSL.test.util import WARNING_TYPE_EXPECTED, NON_ASCII, TestCase, b
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040051from OpenSSL.test.test_crypto import (
Jean-Paul Calderoneda6399a2015-04-13 20:52:29 -040052 cleartextCertificatePEM, cleartextPrivateKeyPEM,
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040053 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
54 root_cert_pem)
55
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050056try:
57 from OpenSSL.SSL import OP_NO_QUERY_MTU
58except ImportError:
59 OP_NO_QUERY_MTU = None
60try:
61 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
62except ImportError:
63 OP_COOKIE_EXCHANGE = None
64try:
65 from OpenSSL.SSL import OP_NO_TICKET
66except ImportError:
67 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040068
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040069try:
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -040070 from OpenSSL.SSL import OP_NO_COMPRESSION
71except ImportError:
72 OP_NO_COMPRESSION = None
73
74try:
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040075 from OpenSSL.SSL import MODE_RELEASE_BUFFERS
76except ImportError:
77 MODE_RELEASE_BUFFERS = None
78
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040079try:
80 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
81except ImportError:
82 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
83
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040084from OpenSSL.SSL import (
85 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
86 SSL_ST_OK, SSL_ST_RENEGOTIATE,
87 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
88 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
89 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
90 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040091
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
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400102def join_bytes_or_unicode(prefix, suffix):
103 """
104 Join two path components of either ``bytes`` or ``unicode``.
105
106 The return type is the same as the type of ``prefix``.
107 """
108 # If the types are the same, nothing special is necessary.
109 if type(prefix) == type(suffix):
110 return join(prefix, suffix)
111
112 # Otherwise, coerce suffix to the type of prefix.
113 if isinstance(prefix, text_type):
114 return join(prefix, suffix.decode(getfilesystemencoding()))
115 else:
116 return join(prefix, suffix.encode(getfilesystemencoding()))
117
118
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400119def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400120 return ok
121
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400122
Rick Deanb1ccd562009-07-09 23:52:39 -0500123def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400124 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400125 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400126 """
127 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500128 port = socket()
129 port.bind(('', 0))
130 port.listen(1)
131 client = socket()
132 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400133 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400134 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500135 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500136
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400137 # Let's pass some unencrypted data to make sure our socket connection is
138 # fine. Just one byte, so we don't have to worry about buffers getting
139 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400140 server.send(b("x"))
141 assert client.recv(1024) == b("x")
142 client.send(b("y"))
143 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500144
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400145 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400146 server.setblocking(False)
147 client.setblocking(False)
Jim Shaver46f28912015-05-29 19:32:16 -0400148
Rick Deanb1ccd562009-07-09 23:52:39 -0500149 return (server, client)
150
151
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400152def handshake(client, server):
153 conns = [client, server]
154 while conns:
155 for conn in conns:
156 try:
157 conn.do_handshake()
158 except WantReadError:
159 pass
160 else:
161 conns.remove(conn)
162
163
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400164def _create_certificate_chain():
165 """
166 Construct and return a chain of certificates.
167
168 1. A new self-signed certificate authority certificate (cacert)
169 2. A new intermediate certificate signed by cacert (icert)
170 3. A new server certificate signed by icert (scert)
171 """
172 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
173
174 # Step 1
175 cakey = PKey()
176 cakey.generate_key(TYPE_RSA, 512)
177 cacert = X509()
178 cacert.get_subject().commonName = "Authority Certificate"
179 cacert.set_issuer(cacert.get_subject())
180 cacert.set_pubkey(cakey)
181 cacert.set_notBefore(b("20000101000000Z"))
182 cacert.set_notAfter(b("20200101000000Z"))
183 cacert.add_extensions([caext])
184 cacert.set_serial_number(0)
185 cacert.sign(cakey, "sha1")
186
187 # Step 2
188 ikey = PKey()
189 ikey.generate_key(TYPE_RSA, 512)
190 icert = X509()
191 icert.get_subject().commonName = "Intermediate Certificate"
192 icert.set_issuer(cacert.get_subject())
193 icert.set_pubkey(ikey)
194 icert.set_notBefore(b("20000101000000Z"))
195 icert.set_notAfter(b("20200101000000Z"))
196 icert.add_extensions([caext])
197 icert.set_serial_number(0)
198 icert.sign(cakey, "sha1")
199
200 # Step 3
201 skey = PKey()
202 skey.generate_key(TYPE_RSA, 512)
203 scert = X509()
204 scert.get_subject().commonName = "Server Certificate"
205 scert.set_issuer(icert.get_subject())
206 scert.set_pubkey(skey)
207 scert.set_notBefore(b("20000101000000Z"))
208 scert.set_notAfter(b("20200101000000Z"))
209 scert.add_extensions([
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200210 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400211 scert.set_serial_number(0)
212 scert.sign(ikey, "sha1")
213
214 return [(cakey, cacert), (ikey, icert), (skey, scert)]
215
216
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400217class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400218 """
219 Helper mixin which defines methods for creating a connected socket pair and
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200220 for forcing two connected SSL sockets to talk to each other via memory
221 BIOs.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400222 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500223 def _loopbackClientFactory(self, socket):
224 client = Connection(Context(TLSv1_METHOD), socket)
225 client.set_connect_state()
226 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400227
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500228 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400229 ctx = Context(TLSv1_METHOD)
230 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
231 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500232 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400233 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500234 return server
235
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500236 def _loopback(self, serverFactory=None, clientFactory=None):
237 if serverFactory is None:
238 serverFactory = self._loopbackServerFactory
239 if clientFactory is None:
240 clientFactory = self._loopbackClientFactory
241
242 (server, client) = socket_pair()
243 server = serverFactory(server)
244 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400245
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400246 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400247
248 server.setblocking(True)
249 client.setblocking(True)
250 return server, client
251
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400252 def _interactInMemory(self, client_conn, server_conn):
253 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900254 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400255 objects. Copy bytes back and forth between their send/receive buffers
256 for as long as there is anything to copy. When there is nothing more
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200257 to copy, return :py:obj:`None`. If one of them actually manages to
258 deliver some application bytes, return a two-tuple of the connection
259 from which the bytes were read and the bytes themselves.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400260 """
261 wrote = True
262 while wrote:
263 # Loop until neither side has anything to say
264 wrote = False
265
266 # Copy stuff from each side's send buffer to the other side's
267 # receive buffer.
268 for (read, write) in [(client_conn, server_conn),
269 (server_conn, client_conn)]:
270
271 # Give the side a chance to generate some more bytes, or
272 # succeed.
273 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400274 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400275 except WantReadError:
276 # It didn't succeed, so we'll hope it generated some
277 # output.
278 pass
279 else:
280 # It did succeed, so we'll stop now and let the caller deal
281 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400282 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400283
284 while True:
285 # Keep copying as long as there's more stuff there.
286 try:
287 dirty = read.bio_read(4096)
288 except WantReadError:
289 # Okay, nothing more waiting to be sent. Stop
290 # processing this send buffer.
291 break
292 else:
293 # Keep track of the fact that someone generated some
294 # output.
295 wrote = True
296 write.bio_write(dirty)
297
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400298 def _handshakeInMemory(self, client_conn, server_conn):
Jean-Paul Calderoneb2b40782014-05-06 08:47:40 -0400299 """
300 Perform the TLS handshake between two :py:class:`Connection` instances
301 connected to each other via memory BIOs.
302 """
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400303 client_conn.set_connect_state()
304 server_conn.set_accept_state()
305
306 for conn in [client_conn, server_conn]:
307 try:
308 conn.do_handshake()
309 except WantReadError:
310 pass
311
312 self._interactInMemory(client_conn, server_conn)
313
314
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400315class VersionTests(TestCase):
316 """
317 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900318 :py:obj:`OpenSSL.SSL.SSLeay_version` and
319 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400320 """
321 def test_OPENSSL_VERSION_NUMBER(self):
322 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900323 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400324 byte and the patch, fix, minor, and major versions in the
325 nibbles above that.
326 """
327 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
328
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400329 def test_SSLeay_version(self):
330 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900331 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400332 one of a number of version strings based on that indicator.
333 """
334 versions = {}
335 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
336 SSLEAY_PLATFORM, SSLEAY_DIR]:
337 version = SSLeay_version(t)
338 versions[version] = t
339 self.assertTrue(isinstance(version, bytes))
340 self.assertEqual(len(versions), 5)
341
342
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400343class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400344 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900345 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400346 """
347 def test_method(self):
348 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200349 :py:obj:`Context` can be instantiated with one of
350 :py:obj:`SSLv2_METHOD`, :py:obj:`SSLv3_METHOD`,
351 :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400352 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400353 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400354 methods = [
355 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
356 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400357 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400358
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400359 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
360 for meth in maybe:
361 try:
362 Context(meth)
363 except (Error, ValueError):
364 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
365 # don't. Difficult to say in advance.
366 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400367
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400368 self.assertRaises(TypeError, Context, "")
369 self.assertRaises(ValueError, Context, 10)
370
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500371 if not PY3:
372 def test_method_long(self):
373 """
374 On Python 2 :py:class:`Context` accepts values of type
375 :py:obj:`long` as well as :py:obj:`int`.
376 """
377 Context(long(TLSv1_METHOD))
378
Rick Deane15b1472009-07-09 15:53:42 -0500379 def test_type(self):
380 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200381 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type
382 object and can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500383 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400384 self.assertIdentical(Context, ContextType)
385 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500386
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400387 def test_use_privatekey(self):
388 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200389 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey`
390 instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400391 """
392 key = PKey()
393 key.generate_key(TYPE_RSA, 128)
394 ctx = Context(TLSv1_METHOD)
395 ctx.use_privatekey(key)
396 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400397
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800398 def test_use_privatekey_file_missing(self):
399 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200400 :py:obj:`Context.use_privatekey_file` raises
401 :py:obj:`OpenSSL.SSL.Error` when passed the name of a file which does
402 not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800403 """
404 ctx = Context(TLSv1_METHOD)
405 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
406
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400407 def _use_privatekey_file_test(self, pemfile, filetype):
408 """
409 Verify that calling ``Context.use_privatekey_file`` with the given
410 arguments does not raise an exception.
411 """
412 key = PKey()
413 key.generate_key(TYPE_RSA, 128)
414
415 with open(pemfile, "wt") as pem:
416 pem.write(
417 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
418 )
419
420 ctx = Context(TLSv1_METHOD)
421 ctx.use_privatekey_file(pemfile, filetype)
422
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400423 def test_use_privatekey_file_bytes(self):
424 """
425 A private key can be specified from a file by passing a ``bytes``
426 instance giving the file name to ``Context.use_privatekey_file``.
427 """
428 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400429 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400430 FILETYPE_PEM,
431 )
432
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400433 def test_use_privatekey_file_unicode(self):
434 """
435 A private key can be specified from a file by passing a ``unicode``
436 instance giving the file name to ``Context.use_privatekey_file``.
437 """
438 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400439 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400440 FILETYPE_PEM,
441 )
442
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500443 if not PY3:
444 def test_use_privatekey_file_long(self):
445 """
446 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
447 filetype of type :py:obj:`long` as well as :py:obj:`int`.
448 """
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400449 self._use_privatekey_file_test(self.mktemp(), long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500450
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800451 def test_use_certificate_wrong_args(self):
452 """
453 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200454 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as
455 an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800456 """
457 ctx = Context(TLSv1_METHOD)
458 self.assertRaises(TypeError, ctx.use_certificate)
459 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200460 self.assertRaises(
461 TypeError, ctx.use_certificate, X509(), "hello, world"
462 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800463
464 def test_use_certificate_uninitialized(self):
465 """
466 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
467 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
468 initialized (ie, which does not actually have any certificate data).
469 """
470 ctx = Context(TLSv1_METHOD)
471 self.assertRaises(Error, ctx.use_certificate, X509())
472
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800473 def test_use_certificate(self):
474 """
475 :py:obj:`Context.use_certificate` sets the certificate which will be
476 used to identify connections created using the context.
477 """
478 # TODO
479 # Hard to assert anything. But we could set a privatekey then ask
480 # OpenSSL if the cert and key agree using check_privatekey. Then as
481 # long as check_privatekey works right we're good...
482 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200483 ctx.use_certificate(
484 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
485 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800486
487 def test_use_certificate_file_wrong_args(self):
488 """
489 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
490 called with zero arguments or more than two arguments, or if the first
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200491 argument is not a byte string or the second argumnent is not an
492 integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800493 """
494 ctx = Context(TLSv1_METHOD)
495 self.assertRaises(TypeError, ctx.use_certificate_file)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200496 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile",
497 object())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800498 self.assertRaises(
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200499 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM,
500 object())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800501 self.assertRaises(
502 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
503 self.assertRaises(
504 TypeError, ctx.use_certificate_file, b"somefile", object())
505
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800506 def test_use_certificate_file_missing(self):
507 """
508 :py:obj:`Context.use_certificate_file` raises
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200509 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does
510 not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800511 """
512 ctx = Context(TLSv1_METHOD)
513 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
514
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400515 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800516 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400517 Verify that calling ``Context.use_certificate_file`` with the given
518 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800519 """
520 # TODO
521 # Hard to assert anything. But we could set a privatekey then ask
522 # OpenSSL if the cert and key agree using check_privatekey. Then as
523 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400524 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800525 pem_file.write(cleartextCertificatePEM)
526
527 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400528 ctx.use_certificate_file(certificate_file)
529
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400530 def test_use_certificate_file_bytes(self):
531 """
532 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
533 ``bytes`` filename) which will be used to identify connections created
534 using the context.
535 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400536 filename = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400537 self._use_certificate_file_test(filename)
538
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400539 def test_use_certificate_file_unicode(self):
540 """
541 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
542 ``bytes`` filename) which will be used to identify connections created
543 using the context.
544 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400545 filename = self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400546 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800547
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500548 if not PY3:
549 def test_use_certificate_file_long(self):
550 """
551 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
552 filetype of type :py:obj:`long` as well as :py:obj:`int`.
553 """
554 pem_filename = self.mktemp()
555 with open(pem_filename, "wb") as pem_file:
556 pem_file.write(cleartextCertificatePEM)
557
558 ctx = Context(TLSv1_METHOD)
559 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
560
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500561 def test_check_privatekey_valid(self):
562 """
563 :py:obj:`Context.check_privatekey` returns :py:obj:`None` if the
564 :py:obj:`Context` instance has been configured to use a matched key and
565 certificate pair.
566 """
567 key = load_privatekey(FILETYPE_PEM, client_key_pem)
568 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
569 context = Context(TLSv1_METHOD)
570 context.use_privatekey(key)
571 context.use_certificate(cert)
572 self.assertIs(None, context.check_privatekey())
573
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500574 def test_check_privatekey_invalid(self):
575 """
576 :py:obj:`Context.check_privatekey` raises :py:obj:`Error` if the
577 :py:obj:`Context` instance has been configured to use a key and
578 certificate pair which don't relate to each other.
579 """
580 key = load_privatekey(FILETYPE_PEM, client_key_pem)
581 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
582 context = Context(TLSv1_METHOD)
583 context.use_privatekey(key)
584 context.use_certificate(cert)
585 self.assertRaises(Error, context.check_privatekey)
586
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500587 def test_check_privatekey_wrong_args(self):
588 """
589 :py:obj:`Context.check_privatekey` raises :py:obj:`TypeError` if called
590 with other than no arguments.
591 """
592 context = Context(TLSv1_METHOD)
593 self.assertRaises(TypeError, context.check_privatekey, object())
594
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400595 def test_set_app_data_wrong_args(self):
596 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200597 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called
598 with other than one argument.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400599 """
600 context = Context(TLSv1_METHOD)
601 self.assertRaises(TypeError, context.set_app_data)
602 self.assertRaises(TypeError, context.set_app_data, None, None)
603
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400604 def test_get_app_data_wrong_args(self):
605 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200606 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called
607 with any arguments.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400608 """
609 context = Context(TLSv1_METHOD)
610 self.assertRaises(TypeError, context.get_app_data, None)
611
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400612 def test_app_data(self):
613 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200614 :py:obj:`Context.set_app_data` stores an object for later retrieval
615 using :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400616 """
617 app_data = object()
618 context = Context(TLSv1_METHOD)
619 context.set_app_data(app_data)
620 self.assertIdentical(context.get_app_data(), app_data)
621
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400622 def test_set_options_wrong_args(self):
623 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200624 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with
625 the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400626 """
627 context = Context(TLSv1_METHOD)
628 self.assertRaises(TypeError, context.set_options)
629 self.assertRaises(TypeError, context.set_options, None)
630 self.assertRaises(TypeError, context.set_options, 1, None)
631
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500632 def test_set_options(self):
633 """
634 :py:obj:`Context.set_options` returns the new options value.
635 """
636 context = Context(TLSv1_METHOD)
637 options = context.set_options(OP_NO_SSLv2)
638 self.assertTrue(OP_NO_SSLv2 & options)
639
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500640 if not PY3:
641 def test_set_options_long(self):
642 """
643 On Python 2 :py:obj:`Context.set_options` accepts values of type
644 :py:obj:`long` as well as :py:obj:`int`.
645 """
646 context = Context(TLSv1_METHOD)
647 options = context.set_options(long(OP_NO_SSLv2))
648 self.assertTrue(OP_NO_SSLv2 & options)
649
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300650 def test_set_mode_wrong_args(self):
651 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200652 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with
653 the wrong number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300654 """
655 context = Context(TLSv1_METHOD)
656 self.assertRaises(TypeError, context.set_mode)
657 self.assertRaises(TypeError, context.set_mode, None)
658 self.assertRaises(TypeError, context.set_mode, 1, None)
659
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400660 if MODE_RELEASE_BUFFERS is not None:
661 def test_set_mode(self):
662 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200663 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the
664 newly set mode.
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400665 """
666 context = Context(TLSv1_METHOD)
667 self.assertTrue(
668 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500669
670 if not PY3:
671 def test_set_mode_long(self):
672 """
673 On Python 2 :py:obj:`Context.set_mode` accepts values of type
674 :py:obj:`long` as well as :py:obj:`int`.
675 """
676 context = Context(TLSv1_METHOD)
677 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
678 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400679 else:
680 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
681
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400682 def test_set_timeout_wrong_args(self):
683 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200684 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with
685 the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400686 """
687 context = Context(TLSv1_METHOD)
688 self.assertRaises(TypeError, context.set_timeout)
689 self.assertRaises(TypeError, context.set_timeout, None)
690 self.assertRaises(TypeError, context.set_timeout, 1, None)
691
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400692 def test_get_timeout_wrong_args(self):
693 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200694 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with
695 any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400696 """
697 context = Context(TLSv1_METHOD)
698 self.assertRaises(TypeError, context.get_timeout, None)
699
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400700 def test_timeout(self):
701 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200702 :py:obj:`Context.set_timeout` sets the session timeout for all
703 connections created using the context object.
704 :py:obj:`Context.get_timeout` retrieves this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400705 """
706 context = Context(TLSv1_METHOD)
707 context.set_timeout(1234)
708 self.assertEquals(context.get_timeout(), 1234)
709
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500710 if not PY3:
711 def test_timeout_long(self):
712 """
713 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
714 `long` as well as int.
715 """
716 context = Context(TLSv1_METHOD)
717 context.set_timeout(long(1234))
718 self.assertEquals(context.get_timeout(), 1234)
719
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400720 def test_set_verify_depth_wrong_args(self):
721 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200722 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called
723 with the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400724 """
725 context = Context(TLSv1_METHOD)
726 self.assertRaises(TypeError, context.set_verify_depth)
727 self.assertRaises(TypeError, context.set_verify_depth, None)
728 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
729
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400730 def test_get_verify_depth_wrong_args(self):
731 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200732 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called
733 with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400734 """
735 context = Context(TLSv1_METHOD)
736 self.assertRaises(TypeError, context.get_verify_depth, None)
737
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400738 def test_verify_depth(self):
739 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200740 :py:obj:`Context.set_verify_depth` sets the number of certificates in
741 a chain to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900742 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400743 """
744 context = Context(TLSv1_METHOD)
745 context.set_verify_depth(11)
746 self.assertEquals(context.get_verify_depth(), 11)
747
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500748 if not PY3:
749 def test_verify_depth_long(self):
750 """
751 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
752 type `long` as well as int.
753 """
754 context = Context(TLSv1_METHOD)
755 context.set_verify_depth(long(11))
756 self.assertEquals(context.get_verify_depth(), 11)
757
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400758 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400759 """
760 Write a new private key out to a new file, encrypted using the given
761 passphrase. Return the path to the new file.
762 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400763 key = PKey()
764 key.generate_key(TYPE_RSA, 128)
765 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400766 fObj = open(pemFile, 'w')
767 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
768 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400769 fObj.close()
770 return pemFile
771
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400772 def test_set_passwd_cb_wrong_args(self):
773 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200774 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called
775 with the wrong arguments or with a non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400776 """
777 context = Context(TLSv1_METHOD)
778 self.assertRaises(TypeError, context.set_passwd_cb)
779 self.assertRaises(TypeError, context.set_passwd_cb, None)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200780 self.assertRaises(
781 TypeError, context.set_passwd_cb, lambda: None, None, None
Hynek Schlawack2c013a92015-09-05 19:33:05 +0200782 ) # pragma: nocover
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400783
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400784 def test_set_passwd_cb(self):
785 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200786 :py:obj:`Context.set_passwd_cb` accepts a callable which will be
787 invoked when a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400788 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400789 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400790 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400791 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200792
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400793 def passphraseCallback(maxlen, verify, extra):
794 calledWith.append((maxlen, verify, extra))
795 return passphrase
796 context = Context(TLSv1_METHOD)
797 context.set_passwd_cb(passphraseCallback)
798 context.use_privatekey_file(pemFile)
799 self.assertTrue(len(calledWith), 1)
800 self.assertTrue(isinstance(calledWith[0][0], int))
801 self.assertTrue(isinstance(calledWith[0][1], int))
802 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400803
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400804 def test_passwd_callback_exception(self):
805 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200806 :py:obj:`Context.use_privatekey_file` propagates any exception raised
807 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400808 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400809 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200810
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400811 def passphraseCallback(maxlen, verify, extra):
812 raise RuntimeError("Sorry, I am a fail.")
813
814 context = Context(TLSv1_METHOD)
815 context.set_passwd_cb(passphraseCallback)
816 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
817
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400818 def test_passwd_callback_false(self):
819 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200820 :py:obj:`Context.use_privatekey_file` raises
821 :py:obj:`OpenSSL.SSL.Error` if the passphrase callback returns a false
822 value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400823 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400824 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200825
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400826 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500827 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400828
829 context = Context(TLSv1_METHOD)
830 context.set_passwd_cb(passphraseCallback)
831 self.assertRaises(Error, context.use_privatekey_file, pemFile)
832
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400833 def test_passwd_callback_non_string(self):
834 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200835 :py:obj:`Context.use_privatekey_file` raises
836 :py:obj:`OpenSSL.SSL.Error` if the passphrase callback returns a true
837 non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400838 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400839 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200840
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400841 def passphraseCallback(maxlen, verify, extra):
842 return 10
843
844 context = Context(TLSv1_METHOD)
845 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800846 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400847
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400848 def test_passwd_callback_too_long(self):
849 """
850 If the passphrase returned by the passphrase callback returns a string
851 longer than the indicated maximum length, it is truncated.
852 """
853 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400854 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400855 pemFile = self._write_encrypted_pem(passphrase)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200856
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400857 def passphraseCallback(maxlen, verify, extra):
858 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400859 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400860
861 context = Context(TLSv1_METHOD)
862 context.set_passwd_cb(passphraseCallback)
863 # This shall succeed because the truncated result is the correct
864 # passphrase.
865 context.use_privatekey_file(pemFile)
866
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400867 def test_set_info_callback(self):
868 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200869 :py:obj:`Context.set_info_callback` accepts a callable which will be
870 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400871 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500872 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400873
874 clientSSL = Connection(Context(TLSv1_METHOD), client)
875 clientSSL.set_connect_state()
876
877 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200878
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400879 def info(conn, where, ret):
880 called.append((conn, where, ret))
881 context = Context(TLSv1_METHOD)
882 context.set_info_callback(info)
883 context.use_certificate(
884 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
885 context.use_privatekey(
886 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
887
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400888 serverSSL = Connection(context, server)
889 serverSSL.set_accept_state()
890
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500891 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400892
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500893 # The callback must always be called with a Connection instance as the
894 # first argument. It would probably be better to split this into
895 # separate tests for client and server side info callbacks so we could
896 # assert it is called with the right Connection instance. It would
897 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500898 notConnections = [
899 conn for (conn, where, ret) in called
900 if not isinstance(conn, Connection)]
901 self.assertEqual(
902 [], notConnections,
903 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400904
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400905 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400906 """
907 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400908 its :py:obj:`load_verify_locations` method with the given arguments.
909 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400910 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500911 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400912
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400913 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400914 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400915 # Require that the server certificate verify properly or the
916 # connection will fail.
917 clientContext.set_verify(
918 VERIFY_PEER,
919 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
920
921 clientSSL = Connection(clientContext, client)
922 clientSSL.set_connect_state()
923
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400924 serverContext = Context(TLSv1_METHOD)
925 serverContext.use_certificate(
926 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
927 serverContext.use_privatekey(
928 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
929
930 serverSSL = Connection(serverContext, server)
931 serverSSL.set_accept_state()
932
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400933 # Without load_verify_locations above, the handshake
934 # will fail:
935 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
936 # 'certificate verify failed')]
937 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400938
939 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400940 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400941
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400942 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400943 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400944 Verify that if path to a file containing a certificate is passed to
945 ``Context.load_verify_locations`` for the ``cafile`` parameter, that
946 certificate is used as a trust root for the purposes of verifying
947 connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400948 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400949 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400950 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400951 fObj.close()
952
953 self._load_verify_locations_test(cafile)
954
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400955 def test_load_verify_bytes_cafile(self):
956 """
957 :py:obj:`Context.load_verify_locations` accepts a file name as a
958 ``bytes`` instance and uses the certificates within for verification
959 purposes.
960 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400961 cafile = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400962 self._load_verify_cafile(cafile)
963
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400964 def test_load_verify_unicode_cafile(self):
965 """
966 :py:obj:`Context.load_verify_locations` accepts a file name as a
967 ``unicode`` instance and uses the certificates within for verification
968 purposes.
969 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -0400970 self._load_verify_cafile(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400971 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -0400972 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400973
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400974 def test_load_verify_invalid_file(self):
975 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200976 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when
977 passed a non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400978 """
979 clientContext = Context(TLSv1_METHOD)
980 self.assertRaises(
981 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400982
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400983 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400984 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400985 Verify that if path to a directory containing certificate files is
986 passed to ``Context.load_verify_locations`` for the ``capath``
987 parameter, those certificates are used as trust roots for the purposes
988 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400989 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400990 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400991 # Hash values computed manually with c_rehash to avoid depending on
992 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
993 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500994 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400995 cafile = join_bytes_or_unicode(capath, name)
996 with open(cafile, 'w') as fObj:
997 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400998
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400999 self._load_verify_locations_test(None, capath)
1000
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001001 def test_load_verify_directory_bytes_capath(self):
1002 """
1003 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1004 ``bytes`` instance and uses the certificates within for verification
1005 purposes.
1006 """
1007 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001008 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001009 )
1010
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001011 def test_load_verify_directory_unicode_capath(self):
1012 """
1013 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1014 ``unicode`` instance and uses the certificates within for verification
1015 purposes.
1016 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001017 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001018 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001019 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001020
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001021 def test_load_verify_locations_wrong_args(self):
1022 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001023 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if
1024 called with the wrong number of arguments or with non-:py:obj:`str`
1025 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001026 """
1027 context = Context(TLSv1_METHOD)
1028 self.assertRaises(TypeError, context.load_verify_locations)
1029 self.assertRaises(TypeError, context.load_verify_locations, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001030 self.assertRaises(
1031 TypeError, context.load_verify_locations, object(), object()
1032 )
1033 self.assertRaises(
1034 TypeError, context.load_verify_locations, None, None, None
1035 )
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001036
Hynek Schlawack734d3022015-09-05 19:19:32 +02001037 @pytest.mark.skipif(
1038 platform == "win32",
1039 reason="set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001040 "See LP#404343 and LP#404344."
Hynek Schlawack734d3022015-09-05 19:19:32 +02001041 )
1042 def test_set_default_verify_paths(self):
1043 """
1044 :py:obj:`Context.set_default_verify_paths` causes the
1045 platform-specific CA certificate locations to be used for
1046 verification purposes.
1047 """
1048 # Testing this requires a server with a certificate signed by one
1049 # of the CAs in the platform CA location. Getting one of those
1050 # costs money. Fortunately (or unfortunately, depending on your
1051 # perspective), it's easy to think of a public server on the
1052 # internet which has such a certificate. Connecting to the network
1053 # in a unit test is bad, but it's the only way I can think of to
1054 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001055
Hynek Schlawack734d3022015-09-05 19:19:32 +02001056 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
1057 context = Context(TLSv1_METHOD)
1058 context.set_default_verify_paths()
1059 context.set_verify(
1060 VERIFY_PEER,
1061 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001062
Hynek Schlawack734d3022015-09-05 19:19:32 +02001063 client = socket()
1064 client.connect(('verisign.com', 443))
1065 clientSSL = Connection(context, client)
1066 clientSSL.set_connect_state()
1067 clientSSL.do_handshake()
1068 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
1069 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001070
1071 def test_set_default_verify_paths_signature(self):
1072 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001073 :py:obj:`Context.set_default_verify_paths` takes no arguments and
1074 raises :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001075 """
1076 context = Context(TLSv1_METHOD)
1077 self.assertRaises(TypeError, context.set_default_verify_paths, None)
1078 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
1079 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001080
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001081 def test_add_extra_chain_cert_invalid_cert(self):
1082 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001083 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if
1084 called with other than one argument or if called with an object which
1085 is not an instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001086 """
1087 context = Context(TLSv1_METHOD)
1088 self.assertRaises(TypeError, context.add_extra_chain_cert)
1089 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001090 self.assertRaises(
1091 TypeError, context.add_extra_chain_cert, object(), object()
1092 )
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001093
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001094 def _handshake_test(self, serverContext, clientContext):
1095 """
1096 Verify that a client and server created with the given contexts can
1097 successfully handshake and communicate.
1098 """
1099 serverSocket, clientSocket = socket_pair()
1100
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001101 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001102 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001103
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001104 client = Connection(clientContext, clientSocket)
1105 client.set_connect_state()
1106
1107 # Make them talk to each other.
1108 # self._interactInMemory(client, server)
1109 for i in range(3):
1110 for s in [client, server]:
1111 try:
1112 s.do_handshake()
1113 except WantReadError:
1114 pass
1115
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001116 def test_set_verify_callback_connection_argument(self):
1117 """
1118 The first argument passed to the verify callback is the
1119 :py:class:`Connection` instance for which verification is taking place.
1120 """
1121 serverContext = Context(TLSv1_METHOD)
1122 serverContext.use_privatekey(
1123 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1124 serverContext.use_certificate(
1125 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1126 serverConnection = Connection(serverContext, None)
1127
1128 class VerifyCallback(object):
1129 def callback(self, connection, *args):
1130 self.connection = connection
1131 return 1
1132
1133 verify = VerifyCallback()
1134 clientContext = Context(TLSv1_METHOD)
1135 clientContext.set_verify(VERIFY_PEER, verify.callback)
1136 clientConnection = Connection(clientContext, None)
1137 clientConnection.set_connect_state()
1138
1139 self._handshakeInMemory(clientConnection, serverConnection)
1140
1141 self.assertIdentical(verify.connection, clientConnection)
1142
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001143 def test_set_verify_callback_exception(self):
1144 """
1145 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1146 exception, verification fails and the exception is propagated to the
1147 caller of :py:obj:`Connection.do_handshake`.
1148 """
1149 serverContext = Context(TLSv1_METHOD)
1150 serverContext.use_privatekey(
1151 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1152 serverContext.use_certificate(
1153 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1154
1155 clientContext = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001156
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001157 def verify_callback(*args):
1158 raise Exception("silly verify failure")
1159 clientContext.set_verify(VERIFY_PEER, verify_callback)
1160
1161 exc = self.assertRaises(
1162 Exception, self._handshake_test, serverContext, clientContext)
1163 self.assertEqual("silly verify failure", str(exc))
1164
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001165 def test_add_extra_chain_cert(self):
1166 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001167 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509`
1168 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001169
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001170 See :py:obj:`_create_certificate_chain` for the details of the
1171 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001172
1173 The chain is tested by starting a server with scert and connecting
1174 to it with a client which trusts cacert and requires verification to
1175 succeed.
1176 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001177 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001178 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1179
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001180 # Dump the CA certificate to a file because that's the only way to load
1181 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001182 for cert, name in [(cacert, 'ca.pem'),
1183 (icert, 'i.pem'),
1184 (scert, 's.pem')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001185 with open(join(self.tmpdir, name), 'w') as f:
1186 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001187
Hynek Schlawack1902c012015-04-16 15:06:41 -04001188 for key, name in [(cakey, 'ca.key'),
1189 (ikey, 'i.key'),
1190 (skey, 's.key')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001191 with open(join(self.tmpdir, name), 'w') as f:
1192 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001193
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001194 # Create the server context
1195 serverContext = Context(TLSv1_METHOD)
1196 serverContext.use_privatekey(skey)
1197 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001198 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001199 serverContext.add_extra_chain_cert(icert)
1200
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001201 # Create the client
1202 clientContext = Context(TLSv1_METHOD)
1203 clientContext.set_verify(
1204 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001205 clientContext.load_verify_locations(join(self.tmpdir, "ca.pem"))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001206
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001207 # Try it out.
1208 self._handshake_test(serverContext, clientContext)
1209
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001210 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001211 """
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001212 Verify that :py:obj:`Context.use_certificate_chain_file` reads a
1213 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001214
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001215 The chain is tested by starting a server with scert and connecting to
1216 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001217 succeed.
1218 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001219 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001220 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1221
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001222 makedirs(certdir)
1223
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001224 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1225 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001226
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001227 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001228 with open(chainFile, 'wb') as fObj:
1229 # Most specific to least general.
1230 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1231 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1232 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1233
1234 with open(caFile, 'w') as fObj:
1235 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001236
1237 serverContext = Context(TLSv1_METHOD)
1238 serverContext.use_certificate_chain_file(chainFile)
1239 serverContext.use_privatekey(skey)
1240
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001241 clientContext = Context(TLSv1_METHOD)
1242 clientContext.set_verify(
1243 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001244 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001245
1246 self._handshake_test(serverContext, clientContext)
1247
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001248 def test_use_certificate_chain_file_bytes(self):
1249 """
1250 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1251 an instance of ``bytes``) to specify additional certificates to use to
1252 construct and verify a trust chain.
1253 """
1254 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001255 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001256 )
1257
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001258 def test_use_certificate_chain_file_unicode(self):
1259 """
1260 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1261 an instance of ``unicode``) to specify additional certificates to use
1262 to construct and verify a trust chain.
1263 """
1264 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001265 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001266 )
1267
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001268 def test_use_certificate_chain_file_wrong_args(self):
1269 """
1270 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1271 if passed zero or more than one argument or when passed a non-byte
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001272 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error`
1273 when passed a bad chain file name (for example, the name of a file
1274 which does not exist).
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001275 """
1276 context = Context(TLSv1_METHOD)
1277 self.assertRaises(TypeError, context.use_certificate_chain_file)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001278 self.assertRaises(
1279 TypeError, context.use_certificate_chain_file, object()
1280 )
1281 self.assertRaises(
1282 TypeError, context.use_certificate_chain_file, b"foo", object()
1283 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001284
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001285 self.assertRaises(
1286 Error, context.use_certificate_chain_file, self.mktemp()
1287 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001288
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001289 # XXX load_client_ca
1290 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001291
1292 def test_get_verify_mode_wrong_args(self):
1293 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001294 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called
1295 with any arguments.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001296 """
1297 context = Context(TLSv1_METHOD)
1298 self.assertRaises(TypeError, context.get_verify_mode, None)
1299
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001300 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001301 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001302 :py:obj:`Context.get_verify_mode` returns the verify mode flags
1303 previously passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001304 """
1305 context = Context(TLSv1_METHOD)
1306 self.assertEquals(context.get_verify_mode(), 0)
1307 context.set_verify(
1308 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1309 self.assertEquals(
1310 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1311
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001312 if not PY3:
1313 def test_set_verify_mode_long(self):
1314 """
1315 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1316 type :py:obj:`long` as well as :py:obj:`int`.
1317 """
1318 context = Context(TLSv1_METHOD)
1319 self.assertEquals(context.get_verify_mode(), 0)
1320 context.set_verify(
1321 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None)
1322 self.assertEquals(
1323 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1324
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001325 def test_load_tmp_dh_wrong_args(self):
1326 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001327 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with
1328 the wrong number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001329 """
1330 context = Context(TLSv1_METHOD)
1331 self.assertRaises(TypeError, context.load_tmp_dh)
1332 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1333 self.assertRaises(TypeError, context.load_tmp_dh, object())
1334
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001335 def test_load_tmp_dh_missing_file(self):
1336 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001337 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the
1338 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001339 """
1340 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001341 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001342
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001343 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001344 """
1345 Verify that calling ``Context.load_tmp_dh`` with the given filename
1346 does not raise an exception.
1347 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001348 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001349 with open(dhfilename, "w") as dhfile:
1350 dhfile.write(dhparam)
1351
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001352 context.load_tmp_dh(dhfilename)
1353 # XXX What should I assert here? -exarkun
1354
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001355 def test_load_tmp_dh_bytes(self):
1356 """
1357 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1358 specified file (given as ``bytes``).
1359 """
1360 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001361 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001362 )
1363
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001364 def test_load_tmp_dh_unicode(self):
1365 """
1366 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1367 specified file (given as ``unicode``).
1368 """
1369 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001370 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001371 )
1372
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001373 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001374 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001375 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001376 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001377 """
1378 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001379 for curve in get_elliptic_curves():
1380 # The only easily "assertable" thing is that it does not raise an
1381 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001382 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001383
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001384 def test_set_cipher_list_bytes(self):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001385 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001386 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
1387 ciphers which connections created with the context object will be able
1388 to choose from.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001389 """
1390 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001391 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001392 conn = Connection(context, None)
1393 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001394
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001395 def test_set_cipher_list_text(self):
1396 """
1397 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
1398 the ciphers which connections created with the context object will be
1399 able to choose from.
1400 """
1401 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -05001402 context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001403 conn = Connection(context, None)
1404 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
1405
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001406 def test_set_cipher_list_wrong_args(self):
1407 """
Jean-Paul Calderone17044832014-01-18 10:20:11 -05001408 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
1409 passed zero arguments or more than one argument or when passed a
1410 non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001411 passed an incorrect cipher list string.
1412 """
1413 context = Context(TLSv1_METHOD)
1414 self.assertRaises(TypeError, context.set_cipher_list)
1415 self.assertRaises(TypeError, context.set_cipher_list, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001416 self.assertRaises(
1417 TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object()
1418 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001419
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001420 self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001421
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001422 def test_set_session_cache_mode_wrong_args(self):
1423 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001424 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1425 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001426 """
1427 context = Context(TLSv1_METHOD)
1428 self.assertRaises(TypeError, context.set_session_cache_mode)
1429 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1430
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001431 def test_get_session_cache_mode_wrong_args(self):
1432 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001433 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1434 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001435 """
1436 context = Context(TLSv1_METHOD)
1437 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1438
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001439 def test_session_cache_mode(self):
1440 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001441 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1442 cached. The setting can be retrieved via
1443 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001444 """
1445 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001446 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001447 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1448 self.assertEqual(SESS_CACHE_OFF, off)
1449 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1450
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001451 if not PY3:
1452 def test_session_cache_mode_long(self):
1453 """
1454 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1455 of type :py:obj:`long` as well as :py:obj:`int`.
1456 """
1457 context = Context(TLSv1_METHOD)
1458 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1459 self.assertEqual(
1460 SESS_CACHE_BOTH, context.get_session_cache_mode())
1461
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001462 def test_get_cert_store(self):
1463 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001464 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store`
1465 instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001466 """
1467 context = Context(TLSv1_METHOD)
1468 store = context.get_cert_store()
1469 self.assertIsInstance(store, X509Store)
1470
1471
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001472class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1473 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001474 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its
1475 interaction with :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001476 """
1477 def test_wrong_args(self):
1478 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001479 :py:obj:`Context.set_tlsext_servername_callback` raises
1480 :py:obj:`TypeError` if called with other than one argument.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001481 """
1482 context = Context(TLSv1_METHOD)
1483 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1484 self.assertRaises(
1485 TypeError, context.set_tlsext_servername_callback, 1, 2)
1486
1487 def test_old_callback_forgotten(self):
1488 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001489 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify
1490 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001491 """
1492 def callback(connection):
1493 pass
1494
1495 def replacement(connection):
1496 pass
1497
1498 context = Context(TLSv1_METHOD)
1499 context.set_tlsext_servername_callback(callback)
1500
1501 tracker = ref(callback)
1502 del callback
1503
1504 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001505
1506 # One run of the garbage collector happens to work on CPython. PyPy
1507 # doesn't collect the underlying object until a second run for whatever
1508 # reason. That's fine, it still demonstrates our code has properly
1509 # dropped the reference.
1510 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001511 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001512
1513 callback = tracker()
1514 if callback is not None:
1515 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001516 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001517 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001518
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001519 def test_no_servername(self):
1520 """
1521 When a client specifies no server name, the callback passed to
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001522 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the
1523 result of :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001524 """
1525 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001526
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001527 def servername(conn):
1528 args.append((conn, conn.get_servername()))
1529 context = Context(TLSv1_METHOD)
1530 context.set_tlsext_servername_callback(servername)
1531
1532 # Lose our reference to it. The Context is responsible for keeping it
1533 # alive now.
1534 del servername
1535 collect()
1536
1537 # Necessary to actually accept the connection
1538 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001539 context.use_certificate(
1540 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001541
1542 # Do a little connection to trigger the logic
1543 server = Connection(context, None)
1544 server.set_accept_state()
1545
1546 client = Connection(Context(TLSv1_METHOD), None)
1547 client.set_connect_state()
1548
1549 self._interactInMemory(server, client)
1550
1551 self.assertEqual([(server, None)], args)
1552
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001553 def test_servername(self):
1554 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001555 When a client specifies a server name in its hello message, the
1556 callback passed to :py:obj:`Contexts.set_tlsext_servername_callback` is
1557 invoked and the result of :py:obj:`Connection.get_servername` is that
1558 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001559 """
1560 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001561
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001562 def servername(conn):
1563 args.append((conn, conn.get_servername()))
1564 context = Context(TLSv1_METHOD)
1565 context.set_tlsext_servername_callback(servername)
1566
1567 # Necessary to actually accept the connection
1568 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001569 context.use_certificate(
1570 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001571
1572 # Do a little connection to trigger the logic
1573 server = Connection(context, None)
1574 server.set_accept_state()
1575
1576 client = Connection(Context(TLSv1_METHOD), None)
1577 client.set_connect_state()
1578 client.set_tlsext_host_name(b("foo1.example.com"))
1579
1580 self._interactInMemory(server, client)
1581
1582 self.assertEqual([(server, b("foo1.example.com"))], args)
1583
1584
Cory Benfield84a121e2014-03-31 20:30:25 +01001585class NextProtoNegotiationTests(TestCase, _LoopbackMixin):
1586 """
1587 Test for Next Protocol Negotiation in PyOpenSSL.
1588 """
Cory Benfieldba1820d2015-04-13 17:39:12 -04001589 if _lib.Cryptography_HAS_NEXTPROTONEG:
1590 def test_npn_success(self):
1591 """
1592 Tests that clients and servers that agree on the negotiated next
1593 protocol can correct establish a connection, and that the agreed
1594 protocol is reported by the connections.
1595 """
1596 advertise_args = []
1597 select_args = []
1598 def advertise(conn):
1599 advertise_args.append((conn,))
1600 return [b'http/1.1', b'spdy/2']
1601 def select(conn, options):
1602 select_args.append((conn, options))
1603 return b'spdy/2'
Cory Benfield84a121e2014-03-31 20:30:25 +01001604
Cory Benfieldba1820d2015-04-13 17:39:12 -04001605 server_context = Context(TLSv1_METHOD)
1606 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001607
Cory Benfieldba1820d2015-04-13 17:39:12 -04001608 client_context = Context(TLSv1_METHOD)
1609 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001610
Cory Benfieldba1820d2015-04-13 17:39:12 -04001611 # Necessary to actually accept the connection
1612 server_context.use_privatekey(
1613 load_privatekey(FILETYPE_PEM, server_key_pem))
1614 server_context.use_certificate(
1615 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001616
Cory Benfieldba1820d2015-04-13 17:39:12 -04001617 # Do a little connection to trigger the logic
1618 server = Connection(server_context, None)
1619 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001620
Cory Benfieldba1820d2015-04-13 17:39:12 -04001621 client = Connection(client_context, None)
1622 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001623
Cory Benfieldba1820d2015-04-13 17:39:12 -04001624 self._interactInMemory(server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001625
Cory Benfieldba1820d2015-04-13 17:39:12 -04001626 self.assertEqual([(server,)], advertise_args)
1627 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001628
Cory Benfieldba1820d2015-04-13 17:39:12 -04001629 self.assertEqual(server.get_next_proto_negotiated(), b'spdy/2')
1630 self.assertEqual(client.get_next_proto_negotiated(), b'spdy/2')
Cory Benfield84a121e2014-03-31 20:30:25 +01001631
1632
Cory Benfieldba1820d2015-04-13 17:39:12 -04001633 def test_npn_client_fail(self):
1634 """
1635 Tests that when clients and servers cannot agree on what protocol
1636 to use next that the TLS connection does not get established.
1637 """
1638 advertise_args = []
1639 select_args = []
1640 def advertise(conn):
1641 advertise_args.append((conn,))
1642 return [b'http/1.1', b'spdy/2']
1643 def select(conn, options):
1644 select_args.append((conn, options))
1645 return b''
Cory Benfield84a121e2014-03-31 20:30:25 +01001646
Cory Benfieldba1820d2015-04-13 17:39:12 -04001647 server_context = Context(TLSv1_METHOD)
1648 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001649
Cory Benfieldba1820d2015-04-13 17:39:12 -04001650 client_context = Context(TLSv1_METHOD)
1651 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001652
Cory Benfieldba1820d2015-04-13 17:39:12 -04001653 # Necessary to actually accept the connection
1654 server_context.use_privatekey(
1655 load_privatekey(FILETYPE_PEM, server_key_pem))
1656 server_context.use_certificate(
1657 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001658
Cory Benfieldba1820d2015-04-13 17:39:12 -04001659 # Do a little connection to trigger the logic
1660 server = Connection(server_context, None)
1661 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001662
Cory Benfieldba1820d2015-04-13 17:39:12 -04001663 client = Connection(client_context, None)
1664 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001665
Cory Benfieldba1820d2015-04-13 17:39:12 -04001666 # If the client doesn't return anything, the connection will fail.
1667 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001668
Cory Benfieldba1820d2015-04-13 17:39:12 -04001669 self.assertEqual([(server,)], advertise_args)
1670 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001671
1672
Cory Benfieldba1820d2015-04-13 17:39:12 -04001673 def test_npn_select_error(self):
1674 """
1675 Test that we can handle exceptions in the select callback. If
1676 select fails it should be fatal to the connection.
1677 """
1678 advertise_args = []
1679 def advertise(conn):
1680 advertise_args.append((conn,))
1681 return [b'http/1.1', b'spdy/2']
1682 def select(conn, options):
1683 raise TypeError
Cory Benfield0ea76e72015-03-22 09:05:28 +00001684
Cory Benfieldba1820d2015-04-13 17:39:12 -04001685 server_context = Context(TLSv1_METHOD)
1686 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001687
Cory Benfieldba1820d2015-04-13 17:39:12 -04001688 client_context = Context(TLSv1_METHOD)
1689 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001690
Cory Benfieldba1820d2015-04-13 17:39:12 -04001691 # Necessary to actually accept the connection
1692 server_context.use_privatekey(
1693 load_privatekey(FILETYPE_PEM, server_key_pem))
1694 server_context.use_certificate(
1695 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001696
Cory Benfieldba1820d2015-04-13 17:39:12 -04001697 # Do a little connection to trigger the logic
1698 server = Connection(server_context, None)
1699 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001700
Cory Benfieldba1820d2015-04-13 17:39:12 -04001701 client = Connection(client_context, None)
1702 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001703
Cory Benfieldba1820d2015-04-13 17:39:12 -04001704 # If the callback throws an exception it should be raised here.
1705 self.assertRaises(
1706 TypeError, self._interactInMemory, server, client
1707 )
1708 self.assertEqual([(server,)], advertise_args)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001709
1710
Cory Benfieldba1820d2015-04-13 17:39:12 -04001711 def test_npn_advertise_error(self):
1712 """
1713 Test that we can handle exceptions in the advertise callback. If
1714 advertise fails no NPN is advertised to the client.
1715 """
1716 select_args = []
1717 def advertise(conn):
1718 raise TypeError
1719 def select(conn, options):
1720 select_args.append((conn, options))
1721 return b''
Cory Benfield0ea76e72015-03-22 09:05:28 +00001722
Cory Benfieldba1820d2015-04-13 17:39:12 -04001723 server_context = Context(TLSv1_METHOD)
1724 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001725
Cory Benfieldba1820d2015-04-13 17:39:12 -04001726 client_context = Context(TLSv1_METHOD)
1727 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001728
Cory Benfieldba1820d2015-04-13 17:39:12 -04001729 # Necessary to actually accept the connection
1730 server_context.use_privatekey(
1731 load_privatekey(FILETYPE_PEM, server_key_pem))
1732 server_context.use_certificate(
1733 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001734
Cory Benfieldba1820d2015-04-13 17:39:12 -04001735 # Do a little connection to trigger the logic
1736 server = Connection(server_context, None)
1737 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001738
Cory Benfieldba1820d2015-04-13 17:39:12 -04001739 client = Connection(client_context, None)
1740 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001741
Cory Benfieldba1820d2015-04-13 17:39:12 -04001742 # If the client doesn't return anything, the connection will fail.
1743 self.assertRaises(
1744 TypeError, self._interactInMemory, server, client
1745 )
1746 self.assertEqual([], select_args)
1747
1748 else:
1749 # No NPN.
1750 def test_npn_not_implemented(self):
1751 # Test the context methods first.
1752 context = Context(TLSv1_METHOD)
1753 fail_methods = [
1754 context.set_npn_advertise_callback,
1755 context.set_npn_select_callback,
1756 ]
1757 for method in fail_methods:
1758 self.assertRaises(
1759 NotImplementedError, method, None
1760 )
1761
1762 # Now test a connection.
1763 conn = Connection(context)
1764 fail_methods = [
1765 conn.get_next_proto_negotiated,
1766 ]
1767 for method in fail_methods:
1768 self.assertRaises(NotImplementedError, method)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001769
1770
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001771
Cory Benfield12eae892014-06-07 15:42:56 +01001772class ApplicationLayerProtoNegotiationTests(TestCase, _LoopbackMixin):
1773 """
1774 Tests for ALPN in PyOpenSSL.
1775 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001776 # Skip tests on versions that don't support ALPN.
1777 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001778
Cory Benfielde46fa842015-04-13 16:50:49 -04001779 def test_alpn_success(self):
1780 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001781 Clients and servers that agree on the negotiated ALPN protocol can
1782 correct establish a connection, and the agreed protocol is reported
1783 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001784 """
1785 select_args = []
1786 def select(conn, options):
1787 select_args.append((conn, options))
1788 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001789
Cory Benfielde46fa842015-04-13 16:50:49 -04001790 client_context = Context(TLSv1_METHOD)
1791 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001792
Cory Benfielde46fa842015-04-13 16:50:49 -04001793 server_context = Context(TLSv1_METHOD)
1794 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001795
Cory Benfielde46fa842015-04-13 16:50:49 -04001796 # Necessary to actually accept the connection
1797 server_context.use_privatekey(
1798 load_privatekey(FILETYPE_PEM, server_key_pem))
1799 server_context.use_certificate(
1800 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001801
Cory Benfielde46fa842015-04-13 16:50:49 -04001802 # Do a little connection to trigger the logic
1803 server = Connection(server_context, None)
1804 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001805
Cory Benfielde46fa842015-04-13 16:50:49 -04001806 client = Connection(client_context, None)
1807 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001808
Cory Benfielde46fa842015-04-13 16:50:49 -04001809 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001810
Cory Benfielde46fa842015-04-13 16:50:49 -04001811 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
1812
1813 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1814 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001815
1816
Cory Benfielde46fa842015-04-13 16:50:49 -04001817 def test_alpn_set_on_connection(self):
1818 """
1819 The same as test_alpn_success, but setting the ALPN protocols on
1820 the connection rather than the context.
1821 """
1822 select_args = []
1823 def select(conn, options):
1824 select_args.append((conn, options))
1825 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001826
Cory Benfielde46fa842015-04-13 16:50:49 -04001827 # Setup the client context but don't set any ALPN protocols.
1828 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001829
Cory Benfielde46fa842015-04-13 16:50:49 -04001830 server_context = Context(TLSv1_METHOD)
1831 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001832
Cory Benfielde46fa842015-04-13 16:50:49 -04001833 # Necessary to actually accept the connection
1834 server_context.use_privatekey(
1835 load_privatekey(FILETYPE_PEM, server_key_pem))
1836 server_context.use_certificate(
1837 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001838
Cory Benfielde46fa842015-04-13 16:50:49 -04001839 # Do a little connection to trigger the logic
1840 server = Connection(server_context, None)
1841 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001842
Cory Benfielde46fa842015-04-13 16:50:49 -04001843 # Set the ALPN protocols on the client connection.
1844 client = Connection(client_context, None)
1845 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1846 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001847
Cory Benfielde46fa842015-04-13 16:50:49 -04001848 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001849
Cory Benfielde46fa842015-04-13 16:50:49 -04001850 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001851
Cory Benfielde46fa842015-04-13 16:50:49 -04001852 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1853 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001854
1855
Cory Benfielde46fa842015-04-13 16:50:49 -04001856 def test_alpn_server_fail(self):
1857 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001858 When clients and servers cannot agree on what protocol to use next
1859 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001860 """
1861 select_args = []
1862 def select(conn, options):
1863 select_args.append((conn, options))
1864 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001865
Cory Benfielde46fa842015-04-13 16:50:49 -04001866 client_context = Context(TLSv1_METHOD)
1867 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001868
Cory Benfielde46fa842015-04-13 16:50:49 -04001869 server_context = Context(TLSv1_METHOD)
1870 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001871
Cory Benfielde46fa842015-04-13 16:50:49 -04001872 # Necessary to actually accept the connection
1873 server_context.use_privatekey(
1874 load_privatekey(FILETYPE_PEM, server_key_pem))
1875 server_context.use_certificate(
1876 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001877
Cory Benfielde46fa842015-04-13 16:50:49 -04001878 # Do a little connection to trigger the logic
1879 server = Connection(server_context, None)
1880 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001881
Cory Benfielde46fa842015-04-13 16:50:49 -04001882 client = Connection(client_context, None)
1883 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001884
Cory Benfielde46fa842015-04-13 16:50:49 -04001885 # If the client doesn't return anything, the connection will fail.
1886 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001887
Cory Benfielde46fa842015-04-13 16:50:49 -04001888 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001889
1890
Cory Benfielde46fa842015-04-13 16:50:49 -04001891 def test_alpn_no_server(self):
1892 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001893 When clients and servers cannot agree on what protocol to use next
1894 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04001895 """
1896 client_context = Context(TLSv1_METHOD)
1897 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04001898
Cory Benfielde46fa842015-04-13 16:50:49 -04001899 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04001900
Cory Benfielde46fa842015-04-13 16:50:49 -04001901 # Necessary to actually accept the connection
1902 server_context.use_privatekey(
1903 load_privatekey(FILETYPE_PEM, server_key_pem))
1904 server_context.use_certificate(
1905 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04001906
Cory Benfielde46fa842015-04-13 16:50:49 -04001907 # Do a little connection to trigger the logic
1908 server = Connection(server_context, None)
1909 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001910
Cory Benfielde46fa842015-04-13 16:50:49 -04001911 client = Connection(client_context, None)
1912 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001913
Cory Benfielde46fa842015-04-13 16:50:49 -04001914 # Do the dance.
1915 self._interactInMemory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04001916
Cory Benfielde46fa842015-04-13 16:50:49 -04001917 self.assertEqual(client.get_alpn_proto_negotiated(), b'')
Cory Benfielde3d57152015-04-11 17:57:35 -04001918
1919
Cory Benfielde46fa842015-04-13 16:50:49 -04001920 def test_alpn_callback_exception(self):
1921 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001922 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04001923 """
1924 select_args = []
1925 def select(conn, options):
1926 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04001927 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001928
Cory Benfielde46fa842015-04-13 16:50:49 -04001929 client_context = Context(TLSv1_METHOD)
1930 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04001931
Cory Benfielde46fa842015-04-13 16:50:49 -04001932 server_context = Context(TLSv1_METHOD)
1933 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04001934
Cory Benfielde46fa842015-04-13 16:50:49 -04001935 # Necessary to actually accept the connection
1936 server_context.use_privatekey(
1937 load_privatekey(FILETYPE_PEM, server_key_pem))
1938 server_context.use_certificate(
1939 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04001940
Cory Benfielde46fa842015-04-13 16:50:49 -04001941 # Do a little connection to trigger the logic
1942 server = Connection(server_context, None)
1943 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001944
Cory Benfielde46fa842015-04-13 16:50:49 -04001945 client = Connection(client_context, None)
1946 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001947
Cory Benfielde46fa842015-04-13 16:50:49 -04001948 self.assertRaises(
1949 TypeError, self._interactInMemory, server, client
1950 )
1951 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfieldf1177e72015-04-12 09:11:49 -04001952
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001953 else:
1954 # No ALPN.
1955 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04001956 """
1957 If ALPN is not in OpenSSL, we should raise NotImplementedError.
1958 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001959 # Test the context methods first.
1960 context = Context(TLSv1_METHOD)
Cory Benfield307e9e62015-04-13 18:21:12 -04001961 self.assertRaises(
1962 NotImplementedError, context.set_alpn_protos, None
1963 )
1964 self.assertRaises(
1965 NotImplementedError, context.set_alpn_select_callback, None
1966 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001967
1968 # Now test a connection.
1969 conn = Connection(context)
Cory Benfield307e9e62015-04-13 18:21:12 -04001970 self.assertRaises(
Alex Gaynor68417232015-09-04 07:56:29 -04001971 NotImplementedError, conn.set_alpn_protos, None
Cory Benfield307e9e62015-04-13 18:21:12 -04001972 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001973
Cory Benfieldf1177e72015-04-12 09:11:49 -04001974
Cory Benfield12eae892014-06-07 15:42:56 +01001975
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001976class SessionTests(TestCase):
1977 """
1978 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1979 """
1980 def test_construction(self):
1981 """
1982 :py:class:`Session` can be constructed with no arguments, creating a new
1983 instance of that type.
1984 """
1985 new_session = Session()
1986 self.assertTrue(isinstance(new_session, Session))
1987
1988
1989 def test_construction_wrong_args(self):
1990 """
1991 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
1992 is raised.
1993 """
1994 self.assertRaises(TypeError, Session, 123)
1995 self.assertRaises(TypeError, Session, "hello")
1996 self.assertRaises(TypeError, Session, object())
1997
1998
1999
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002000class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05002001 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002002 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002003 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002004 # XXX get_peer_certificate -> None
2005 # XXX sock_shutdown
2006 # XXX master_key -> TypeError
2007 # XXX server_random -> TypeError
2008 # XXX state_string
2009 # XXX connect -> TypeError
2010 # XXX connect_ex -> TypeError
2011 # XXX set_connect_state -> TypeError
2012 # XXX set_accept_state -> TypeError
2013 # XXX renegotiate_pending
2014 # XXX do_handshake -> TypeError
2015 # XXX bio_read -> TypeError
2016 # XXX recv -> TypeError
2017 # XXX send -> TypeError
2018 # XXX bio_write -> TypeError
2019
Rick Deane15b1472009-07-09 15:53:42 -05002020 def test_type(self):
2021 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002022 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002023 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002024 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002025 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05002026 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002027 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002028
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002029
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002030 def test_get_context(self):
2031 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002032 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
2033 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002034 """
2035 context = Context(TLSv1_METHOD)
2036 connection = Connection(context, None)
2037 self.assertIdentical(connection.get_context(), context)
2038
2039
2040 def test_get_context_wrong_args(self):
2041 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002042 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002043 arguments.
2044 """
2045 connection = Connection(Context(TLSv1_METHOD), None)
2046 self.assertRaises(TypeError, connection.get_context, None)
2047
2048
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002049 def test_set_context_wrong_args(self):
2050 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002051 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
2052 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002053 than 1.
2054 """
2055 ctx = Context(TLSv1_METHOD)
2056 connection = Connection(ctx, None)
2057 self.assertRaises(TypeError, connection.set_context)
2058 self.assertRaises(TypeError, connection.set_context, object())
2059 self.assertRaises(TypeError, connection.set_context, "hello")
2060 self.assertRaises(TypeError, connection.set_context, 1)
2061 self.assertRaises(TypeError, connection.set_context, 1, 2)
2062 self.assertRaises(
2063 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
2064 self.assertIdentical(ctx, connection.get_context())
2065
2066
2067 def test_set_context(self):
2068 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002069 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002070 for the connection.
2071 """
2072 original = Context(SSLv23_METHOD)
2073 replacement = Context(TLSv1_METHOD)
2074 connection = Connection(original, None)
2075 connection.set_context(replacement)
2076 self.assertIdentical(replacement, connection.get_context())
2077 # Lose our references to the contexts, just in case the Connection isn't
2078 # properly managing its own contributions to their reference counts.
2079 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002080 collect()
2081
2082
2083 def test_set_tlsext_host_name_wrong_args(self):
2084 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002085 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002086 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09002087 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002088 """
2089 conn = Connection(Context(TLSv1_METHOD), None)
2090 self.assertRaises(TypeError, conn.set_tlsext_host_name)
2091 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
2092 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
2093 self.assertRaises(
2094 TypeError, conn.set_tlsext_host_name, b("with\0null"))
2095
Abraham Martinc5484ba2015-03-25 15:33:05 +00002096 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002097 # On Python 3.x, don't accidentally implicitly convert from text.
2098 self.assertRaises(
2099 TypeError,
2100 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002101
2102
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002103 def test_get_servername_wrong_args(self):
2104 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002105 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002106 arguments.
2107 """
2108 connection = Connection(Context(TLSv1_METHOD), None)
2109 self.assertRaises(TypeError, connection.get_servername, object())
2110 self.assertRaises(TypeError, connection.get_servername, 1)
2111 self.assertRaises(TypeError, connection.get_servername, "hello")
2112
2113
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002114 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002115 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002116 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002117 immediate read.
2118 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002119 connection = Connection(Context(TLSv1_METHOD), None)
2120 self.assertEquals(connection.pending(), 0)
2121
2122
2123 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002124 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002125 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002126 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002127 connection = Connection(Context(TLSv1_METHOD), None)
2128 self.assertRaises(TypeError, connection.pending, None)
2129
2130
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002131 def test_peek(self):
2132 """
2133 :py:obj:`Connection.recv` peeks into the connection if :py:obj:`socket.MSG_PEEK` is passed.
2134 """
2135 server, client = self._loopback()
2136 server.send(b('xy'))
2137 self.assertEqual(client.recv(2, MSG_PEEK), b('xy'))
2138 self.assertEqual(client.recv(2, MSG_PEEK), b('xy'))
2139 self.assertEqual(client.recv(2), b('xy'))
2140
2141
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002142 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002143 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002144 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002145 argument or with the wrong number of arguments.
2146 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002147 connection = Connection(Context(TLSv1_METHOD), socket())
2148 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002149 self.assertRaises(TypeError, connection.connect)
2150 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002151
kjavfe508d62015-09-02 12:20:35 +01002152 def test_connection_undefined_attr(self):
2153 """
2154 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
2155 argument or with the wrong number of arguments.
2156 """
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002157
kjavfe508d62015-09-02 12:20:35 +01002158 def attr_access_test(connection):
2159 return connection.an_attribute_which_is_not_defined
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002160
kjavfe508d62015-09-02 12:20:35 +01002161 connection = Connection(Context(TLSv1_METHOD), None)
2162 self.assertRaises(AttributeError, attr_access_test, connection)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002163
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002164 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002165 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002166 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002167 connect method raises it.
2168 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002169 client = socket()
2170 context = Context(TLSv1_METHOD)
2171 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002172 # pytest.raises here doesn't work because of a bug in py.test on Python
2173 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002174 try:
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002175 clientSSL.connect(("127.0.0.1", 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002176 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002177 exc = e
2178 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002179
2180 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002181 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002182 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002183 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002184 port = socket()
2185 port.bind(('', 0))
2186 port.listen(3)
2187
2188 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002189 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2190 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002191
2192
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002193 if platform == "darwin":
2194 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2195 else:
2196 def test_connect_ex(self):
2197 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002198 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002199 errno instead of raising an exception.
2200 """
2201 port = socket()
2202 port.bind(('', 0))
2203 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002204
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002205 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2206 clientSSL.setblocking(False)
2207 result = clientSSL.connect_ex(port.getsockname())
2208 expected = (EINPROGRESS, EWOULDBLOCK)
2209 self.assertTrue(
2210 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002211
2212
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002213 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002214 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002215 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002216 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002217 connection = Connection(Context(TLSv1_METHOD), socket())
2218 self.assertRaises(TypeError, connection.accept, None)
2219
2220
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002221 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002222 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002223 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
2224 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002225 connection originated from.
2226 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002227 ctx = Context(TLSv1_METHOD)
2228 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2229 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002230 port = socket()
2231 portSSL = Connection(ctx, port)
2232 portSSL.bind(('', 0))
2233 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002234
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002235 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002236
2237 # Calling portSSL.getsockname() here to get the server IP address sounds
2238 # great, but frequently fails on Windows.
2239 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002240
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002241 serverSSL, address = portSSL.accept()
2242
2243 self.assertTrue(isinstance(serverSSL, Connection))
2244 self.assertIdentical(serverSSL.get_context(), ctx)
2245 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002246
2247
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002248 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002249 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002250 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002251 number of arguments or with arguments other than integers.
2252 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002253 connection = Connection(Context(TLSv1_METHOD), None)
2254 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04002255 self.assertRaises(TypeError, connection.get_shutdown, None)
2256 self.assertRaises(TypeError, connection.set_shutdown)
2257 self.assertRaises(TypeError, connection.set_shutdown, None)
2258 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002259
2260
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002261 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002262 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002263 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002264 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002265 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002266 self.assertFalse(server.shutdown())
2267 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002268 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002269 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
2270 client.shutdown()
Alex Gaynor43307782015-09-04 09:05:45 -04002271 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002272 self.assertRaises(ZeroReturnError, server.recv, 1024)
Alex Gaynor43307782015-09-04 09:05:45 -04002273 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002274
2275
Paul Aurichc85e0862015-01-08 08:34:33 -08002276 def test_shutdown_closed(self):
2277 """
2278 If the underlying socket is closed, :py:obj:`Connection.shutdown` propagates the
2279 write error from the low level write call.
2280 """
2281 server, client = self._loopback()
2282 server.sock_shutdown(2)
2283 exc = self.assertRaises(SysCallError, server.shutdown)
2284 if platform == "win32":
2285 self.assertEqual(exc.args[0], ESHUTDOWN)
2286 else:
2287 self.assertEqual(exc.args[0], EPIPE)
2288
2289
Glyph89389472015-04-14 17:29:26 -04002290 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002291 """
Glyph89389472015-04-14 17:29:26 -04002292 If the underlying connection is truncated, :obj:`Connection.shutdown`
2293 raises an :obj:`Error`.
Glyph6064ec32015-04-14 16:38:22 -04002294 """
Glyph89389472015-04-14 17:29:26 -04002295 server_ctx = Context(TLSv1_METHOD)
2296 client_ctx = Context(TLSv1_METHOD)
2297 server_ctx.use_privatekey(
2298 load_privatekey(FILETYPE_PEM, server_key_pem))
2299 server_ctx.use_certificate(
2300 load_certificate(FILETYPE_PEM, server_cert_pem))
2301 server = Connection(server_ctx, None)
2302 client = Connection(client_ctx, None)
2303 self._handshakeInMemory(client, server)
2304 self.assertEqual(server.shutdown(), False)
2305 self.assertRaises(WantReadError, server.shutdown)
2306 server.bio_shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002307 self.assertRaises(Error, server.shutdown)
2308
2309
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002310 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002311 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002312 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002313 process.
2314 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002315 connection = Connection(Context(TLSv1_METHOD), socket())
2316 connection.set_shutdown(RECEIVED_SHUTDOWN)
2317 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2318
2319
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002320 if not PY3:
2321 def test_set_shutdown_long(self):
2322 """
2323 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
2324 of type :py:obj:`long` as well as :py:obj:`int`.
2325 """
2326 connection = Connection(Context(TLSv1_METHOD), socket())
2327 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
2328 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2329
2330
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002331 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002332 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002333 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
2334 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002335 with any arguments.
2336 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002337 conn = Connection(Context(TLSv1_METHOD), None)
2338 self.assertRaises(TypeError, conn.get_app_data, None)
2339 self.assertRaises(TypeError, conn.set_app_data)
2340 self.assertRaises(TypeError, conn.set_app_data, None, None)
2341
2342
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002343 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002344 """
2345 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002346 :py:obj:`Connection.set_app_data` and later retrieved with
2347 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002348 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002349 conn = Connection(Context(TLSv1_METHOD), None)
2350 app_data = object()
2351 conn.set_app_data(app_data)
2352 self.assertIdentical(conn.get_app_data(), app_data)
2353
2354
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002355 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002356 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002357 :py:obj:`Connection.makefile` is not implemented and calling that method raises
2358 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002359 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002360 conn = Connection(Context(TLSv1_METHOD), None)
2361 self.assertRaises(NotImplementedError, conn.makefile)
2362
2363
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002364 def test_get_peer_cert_chain_wrong_args(self):
2365 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002366 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002367 arguments.
2368 """
2369 conn = Connection(Context(TLSv1_METHOD), None)
2370 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
2371 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
2372 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
2373 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
2374
2375
2376 def test_get_peer_cert_chain(self):
2377 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002378 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002379 the connected server returned for the certification verification.
2380 """
2381 chain = _create_certificate_chain()
2382 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2383
2384 serverContext = Context(TLSv1_METHOD)
2385 serverContext.use_privatekey(skey)
2386 serverContext.use_certificate(scert)
2387 serverContext.add_extra_chain_cert(icert)
2388 serverContext.add_extra_chain_cert(cacert)
2389 server = Connection(serverContext, None)
2390 server.set_accept_state()
2391
2392 # Create the client
2393 clientContext = Context(TLSv1_METHOD)
2394 clientContext.set_verify(VERIFY_NONE, verify_cb)
2395 client = Connection(clientContext, None)
2396 client.set_connect_state()
2397
2398 self._interactInMemory(client, server)
2399
2400 chain = client.get_peer_cert_chain()
2401 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002402 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002403 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002404 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002405 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002406 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002407 "Authority Certificate", chain[2].get_subject().CN)
2408
2409
2410 def test_get_peer_cert_chain_none(self):
2411 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002412 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002413 certificate chain.
2414 """
2415 ctx = Context(TLSv1_METHOD)
2416 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2417 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2418 server = Connection(ctx, None)
2419 server.set_accept_state()
2420 client = Connection(Context(TLSv1_METHOD), None)
2421 client.set_connect_state()
2422 self._interactInMemory(client, server)
2423 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002424
2425
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002426 def test_get_session_wrong_args(self):
2427 """
2428 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
2429 with any arguments.
2430 """
2431 ctx = Context(TLSv1_METHOD)
2432 server = Connection(ctx, None)
2433 self.assertRaises(TypeError, server.get_session, 123)
2434 self.assertRaises(TypeError, server.get_session, "hello")
2435 self.assertRaises(TypeError, server.get_session, object())
2436
2437
2438 def test_get_session_unconnected(self):
2439 """
2440 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
2441 an object which has not been connected.
2442 """
2443 ctx = Context(TLSv1_METHOD)
2444 server = Connection(ctx, None)
2445 session = server.get_session()
2446 self.assertIdentical(None, session)
2447
2448
2449 def test_server_get_session(self):
2450 """
2451 On the server side of a connection, :py:obj:`Connection.get_session`
2452 returns a :py:class:`Session` instance representing the SSL session for
2453 that connection.
2454 """
2455 server, client = self._loopback()
2456 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002457 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002458
2459
2460 def test_client_get_session(self):
2461 """
2462 On the client side of a connection, :py:obj:`Connection.get_session`
2463 returns a :py:class:`Session` instance representing the SSL session for
2464 that connection.
2465 """
2466 server, client = self._loopback()
2467 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002468 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002469
2470
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002471 def test_set_session_wrong_args(self):
2472 """
2473 If called with an object that is not an instance of :py:class:`Session`,
2474 or with other than one argument, :py:obj:`Connection.set_session` raises
2475 :py:obj:`TypeError`.
2476 """
2477 ctx = Context(TLSv1_METHOD)
2478 connection = Connection(ctx, None)
2479 self.assertRaises(TypeError, connection.set_session)
2480 self.assertRaises(TypeError, connection.set_session, 123)
2481 self.assertRaises(TypeError, connection.set_session, "hello")
2482 self.assertRaises(TypeError, connection.set_session, object())
2483 self.assertRaises(
2484 TypeError, connection.set_session, Session(), Session())
2485
2486
2487 def test_client_set_session(self):
2488 """
2489 :py:obj:`Connection.set_session`, when used prior to a connection being
2490 established, accepts a :py:class:`Session` instance and causes an
2491 attempt to re-use the session it represents when the SSL handshake is
2492 performed.
2493 """
2494 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2495 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2496 ctx = Context(TLSv1_METHOD)
2497 ctx.use_privatekey(key)
2498 ctx.use_certificate(cert)
2499 ctx.set_session_id("unity-test")
2500
2501 def makeServer(socket):
2502 server = Connection(ctx, socket)
2503 server.set_accept_state()
2504 return server
2505
2506 originalServer, originalClient = self._loopback(
2507 serverFactory=makeServer)
2508 originalSession = originalClient.get_session()
2509
2510 def makeClient(socket):
2511 client = self._loopbackClientFactory(socket)
2512 client.set_session(originalSession)
2513 return client
2514 resumedServer, resumedClient = self._loopback(
2515 serverFactory=makeServer,
2516 clientFactory=makeClient)
2517
2518 # This is a proxy: in general, we have no access to any unique
2519 # identifier for the session (new enough versions of OpenSSL expose a
2520 # hash which could be usable, but "new enough" is very, very new).
2521 # Instead, exploit the fact that the master key is re-used if the
2522 # session is re-used. As long as the master key for the two connections
2523 # is the same, the session was re-used!
2524 self.assertEqual(
2525 originalServer.master_key(), resumedServer.master_key())
2526
2527
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002528 def test_set_session_wrong_method(self):
2529 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002530 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
2531 instance associated with a context using a different SSL method than the
2532 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
2533 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002534 """
2535 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2536 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2537 ctx = Context(TLSv1_METHOD)
2538 ctx.use_privatekey(key)
2539 ctx.use_certificate(cert)
2540 ctx.set_session_id("unity-test")
2541
2542 def makeServer(socket):
2543 server = Connection(ctx, socket)
2544 server.set_accept_state()
2545 return server
2546
2547 originalServer, originalClient = self._loopback(
2548 serverFactory=makeServer)
2549 originalSession = originalClient.get_session()
2550
2551 def makeClient(socket):
2552 # Intentionally use a different, incompatible method here.
2553 client = Connection(Context(SSLv3_METHOD), socket)
2554 client.set_connect_state()
2555 client.set_session(originalSession)
2556 return client
2557
2558 self.assertRaises(
2559 Error,
2560 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2561
2562
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002563 def test_wantWriteError(self):
2564 """
2565 :py:obj:`Connection` methods which generate output raise
2566 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2567 fail indicating a should-write state.
2568 """
2569 client_socket, server_socket = socket_pair()
2570 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002571 # anything. Only write a single byte at a time so we can be sure we
2572 # completely fill the buffer. Even though the socket API is allowed to
2573 # signal a short write via its return value it seems this doesn't
2574 # always happen on all platforms (FreeBSD and OS X particular) for the
2575 # very last bit of available buffer space.
2576 msg = b"x"
2577 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002578 try:
2579 client_socket.send(msg)
2580 except error as e:
2581 if e.errno == EWOULDBLOCK:
2582 break
2583 raise
2584 else:
2585 self.fail(
2586 "Failed to fill socket buffer, cannot test BIO want write")
2587
2588 ctx = Context(TLSv1_METHOD)
2589 conn = Connection(ctx, client_socket)
2590 # Client's speak first, so make it an SSL client
2591 conn.set_connect_state()
2592 self.assertRaises(WantWriteError, conn.do_handshake)
2593
2594 # XXX want_read
2595
Fedor Brunner416f4a12014-03-28 13:18:38 +01002596 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002597 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002598 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2599 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002600 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002601 ctx = Context(TLSv1_METHOD)
2602 connection = Connection(ctx, None)
2603 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002604
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002605
Fedor Brunner416f4a12014-03-28 13:18:38 +01002606 def test_get_peer_finished_before_connect(self):
2607 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002608 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2609 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002610 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002611 ctx = Context(TLSv1_METHOD)
2612 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002613 self.assertEqual(connection.get_peer_finished(), None)
2614
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002615
Fedor Brunner416f4a12014-03-28 13:18:38 +01002616 def test_get_finished(self):
2617 """
2618 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002619 message send from client, or server. Finished messages are send during
2620 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002621 """
2622
Fedor Brunner5747b932014-03-05 14:22:34 +01002623 server, client = self._loopback()
2624
2625 self.assertNotEqual(server.get_finished(), None)
2626 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002627
Jean-Paul Calderoned979f232014-03-30 11:58:00 -04002628
Fedor Brunner416f4a12014-03-28 13:18:38 +01002629 def test_get_peer_finished(self):
2630 """
2631 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002632 message received from client, or server. Finished messages are send
2633 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002634 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002635 server, client = self._loopback()
2636
2637 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002638 self.assertTrue(len(server.get_peer_finished()) > 0)
2639
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002640
Fedor Brunner416f4a12014-03-28 13:18:38 +01002641 def test_tls_finished_message_symmetry(self):
2642 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002643 The TLS Finished message send by server must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002644 received by client.
2645
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002646 The TLS Finished message send by client must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002647 received by server.
2648 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002649 server, client = self._loopback()
2650
Fedor Brunner5747b932014-03-05 14:22:34 +01002651 self.assertEqual(server.get_finished(), client.get_peer_finished())
2652 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002653
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002654
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002655 def test_get_cipher_name_before_connect(self):
2656 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002657 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2658 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002659 """
2660 ctx = Context(TLSv1_METHOD)
2661 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002662 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002663
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002664
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002665 def test_get_cipher_name(self):
2666 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002667 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2668 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002669 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002670 server, client = self._loopback()
2671 server_cipher_name, client_cipher_name = \
2672 server.get_cipher_name(), client.get_cipher_name()
2673
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002674 self.assertIsInstance(server_cipher_name, text_type)
2675 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002676
2677 self.assertEqual(server_cipher_name, client_cipher_name)
2678
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002679
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002680 def test_get_cipher_version_before_connect(self):
2681 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002682 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2683 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002684 """
2685 ctx = Context(TLSv1_METHOD)
2686 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002687 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002688
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002689
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002690 def test_get_cipher_version(self):
2691 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002692 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2693 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002694 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002695 server, client = self._loopback()
2696 server_cipher_version, client_cipher_version = \
2697 server.get_cipher_version(), client.get_cipher_version()
2698
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002699 self.assertIsInstance(server_cipher_version, text_type)
2700 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002701
2702 self.assertEqual(server_cipher_version, client_cipher_version)
2703
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002704
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002705 def test_get_cipher_bits_before_connect(self):
2706 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002707 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2708 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002709 """
2710 ctx = Context(TLSv1_METHOD)
2711 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002712 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002713
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002714
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002715 def test_get_cipher_bits(self):
2716 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002717 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2718 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002719 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002720 server, client = self._loopback()
2721 server_cipher_bits, client_cipher_bits = \
2722 server.get_cipher_bits(), client.get_cipher_bits()
2723
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002724 self.assertIsInstance(server_cipher_bits, int)
2725 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002726
2727 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002728
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002729
Jim Shaverabff1882015-05-27 09:15:55 -04002730 def test_get_protocol_version_name(self):
2731 """
2732 :py:obj:`Connection.get_protocol_version_name()` returns a string
2733 giving the protocol version of the current connection.
2734 """
2735 server, client = self._loopback()
2736 client_protocol_version_name = client.get_protocol_version_name()
2737 server_protocol_version_name = server.get_protocol_version_name()
2738
Jim Shaver58d25732015-05-28 11:52:32 -04002739 self.assertIsInstance(server_protocol_version_name, text_type)
2740 self.assertIsInstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002741
2742 self.assertEqual(server_protocol_version_name, client_protocol_version_name)
2743
2744
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002745 def test_get_protocol_version(self):
2746 """
Alex Gaynor43307782015-09-04 09:05:45 -04002747 :py:obj:`Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002748 giving the protocol version of the current connection.
2749 """
2750 server, client = self._loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002751 client_protocol_version = client.get_protocol_version()
2752 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002753
Jim Shaverabff1882015-05-27 09:15:55 -04002754 self.assertIsInstance(server_protocol_version, int)
2755 self.assertIsInstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002756
2757 self.assertEqual(server_protocol_version, client_protocol_version)
2758
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002759
Jim Shaver208438c2015-05-28 09:52:38 -04002760
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002761class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002762 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002763 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002764 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002765 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002766 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002767 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002768 arguments.
2769 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002770 connection = Connection(Context(TLSv1_METHOD), None)
2771 self.assertRaises(TypeError, connection.get_cipher_list, None)
2772
2773
2774 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002775 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002776 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2777 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002778 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002779 connection = Connection(Context(TLSv1_METHOD), None)
2780 ciphers = connection.get_cipher_list()
2781 self.assertTrue(isinstance(ciphers, list))
2782 for cipher in ciphers:
2783 self.assertTrue(isinstance(cipher, str))
2784
2785
2786
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002787class ConnectionSendTests(TestCase, _LoopbackMixin):
2788 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002789 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002790 """
2791 def test_wrong_args(self):
2792 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002793 When called with arguments other than string argument for its first
2794 parameter or more than two arguments, :py:obj:`Connection.send` raises
2795 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002796 """
2797 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002798 self.assertRaises(TypeError, connection.send)
2799 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002800 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002801
2802
2803 def test_short_bytes(self):
2804 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002805 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002806 and returns the number of bytes sent.
2807 """
2808 server, client = self._loopback()
2809 count = server.send(b('xy'))
2810 self.assertEquals(count, 2)
2811 self.assertEquals(client.recv(2), b('xy'))
2812
Abraham Martinef063482015-03-25 14:06:24 +00002813
2814 def test_text(self):
2815 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002816 When passed a text, :py:obj:`Connection.send` transmits all of it and
2817 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002818 """
2819 server, client = self._loopback()
2820 with catch_warnings(record=True) as w:
2821 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002822 count = server.send(b"xy".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002823 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002824 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002825 WARNING_TYPE_EXPECTED
2826 ),
2827 str(w[-1].message)
2828 )
2829 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinef063482015-03-25 14:06:24 +00002830 self.assertEquals(count, 2)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002831 self.assertEquals(client.recv(2), b"xy")
Abraham Martinef063482015-03-25 14:06:24 +00002832
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002833 try:
2834 memoryview
2835 except NameError:
2836 "cannot test sending memoryview without memoryview"
2837 else:
2838 def test_short_memoryview(self):
2839 """
2840 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002841 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002842 bytes sent.
2843 """
2844 server, client = self._loopback()
2845 count = server.send(memoryview(b('xy')))
2846 self.assertEquals(count, 2)
2847 self.assertEquals(client.recv(2), b('xy'))
2848
2849
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002850 try:
2851 buffer
2852 except NameError:
2853 "cannot test sending buffer without buffer"
2854 else:
2855 def test_short_buffer(self):
2856 """
2857 When passed a buffer containing a small number of bytes,
2858 :py:obj:`Connection.send` transmits all of them and returns the number of
2859 bytes sent.
2860 """
2861 server, client = self._loopback()
2862 count = server.send(buffer(b('xy')))
2863 self.assertEquals(count, 2)
2864 self.assertEquals(client.recv(2), b('xy'))
2865
2866
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002867
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002868def _make_memoryview(size):
2869 """
2870 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2871 size.
2872 """
2873 return memoryview(bytearray(size))
2874
2875
2876
Cory Benfield62d10332014-06-15 10:03:41 +01002877class ConnectionRecvIntoTests(TestCase, _LoopbackMixin):
2878 """
2879 Tests for :py:obj:`Connection.recv_into`
2880 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002881 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002882 """
2883 Assert that when the given buffer is passed to
2884 ``Connection.recv_into``, whatever bytes are available to be received
2885 that fit into that buffer are written into that buffer.
2886 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002887 output_buffer = factory(5)
2888
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002889 server, client = self._loopback()
2890 server.send(b('xy'))
2891
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002892 self.assertEqual(client.recv_into(output_buffer), 2)
2893 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002894
2895
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002896 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002897 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002898 :py:obj:`Connection.recv_into` can be passed a ``bytearray`` instance
2899 and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002900 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002901 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002902
2903
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002904 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002905 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002906 Assert that when the given buffer is passed to ``Connection.recv_into``
2907 along with a value for ``nbytes`` that is less than the size of that
2908 buffer, only ``nbytes`` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002909 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002910 output_buffer = factory(10)
2911
Cory Benfield62d10332014-06-15 10:03:41 +01002912 server, client = self._loopback()
2913 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002914
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002915 self.assertEqual(client.recv_into(output_buffer, 5), 5)
2916 self.assertEqual(
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002917 output_buffer, bytearray(b('abcde\x00\x00\x00\x00\x00'))
2918 )
2919
2920
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002921 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002922 """
2923 When called with a ``bytearray`` instance,
2924 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter and
2925 doesn't copy in more than that number of bytes.
2926 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002927 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002928
2929
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002930 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002931 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002932 Assert that if there are more bytes available to be read from the
2933 receive buffer than would fit into the buffer passed to
2934 :py:obj:`Connection.recv_into`, only as many as fit are written into
2935 it.
Cory Benfield62d10332014-06-15 10:03:41 +01002936 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002937 output_buffer = factory(5)
2938
Cory Benfield62d10332014-06-15 10:03:41 +01002939 server, client = self._loopback()
2940 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002941
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002942 self.assertEqual(client.recv_into(output_buffer), 5)
2943 self.assertEqual(output_buffer, bytearray(b('abcde')))
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002944 rest = client.recv(5)
2945 self.assertEqual(b('fghij'), rest)
2946
2947
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002948 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002949 """
2950 When called with a ``bytearray`` instance,
2951 :py:obj:`Connection.recv_into` respects the size of the array and
2952 doesn't write more bytes into it than will fit.
2953 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002954 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002955
2956
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002957 def _really_doesnt_overfill_test(self, factory):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002958 """
2959 Assert that if the value given by ``nbytes`` is greater than the actual
2960 size of the output buffer passed to :py:obj:`Connection.recv_into`, the
2961 behavior is as if no value was given for ``nbytes`` at all.
2962 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002963 output_buffer = factory(5)
2964
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002965 server, client = self._loopback()
2966 server.send(b('abcdefghij'))
2967
2968 self.assertEqual(client.recv_into(output_buffer, 50), 5)
2969 self.assertEqual(output_buffer, bytearray(b('abcde')))
2970 rest = client.recv(5)
2971 self.assertEqual(b('fghij'), rest)
2972
2973
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002974 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002975 """
2976 When called with a ``bytearray`` instance and an ``nbytes`` value that
2977 is too large, :py:obj:`Connection.recv_into` respects the size of the
2978 array and not the ``nbytes`` value and doesn't write more bytes into
2979 the buffer than will fit.
2980 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002981 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002982
2983
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002984 def test_peek(self):
2985
2986 server, client = self._loopback()
2987 server.send(b('xy'))
2988
2989 for _ in range(2):
2990 output_buffer = bytearray(5)
2991 self.assertEqual(client.recv_into(output_buffer, flags=MSG_PEEK), 2)
2992 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
2993
2994
Cory Benfield62d10332014-06-15 10:03:41 +01002995 try:
2996 memoryview
2997 except NameError:
2998 "cannot test recv_into memoryview without memoryview"
2999 else:
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04003000 def test_memoryview_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01003001 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04003002 :py:obj:`Connection.recv_into` can be passed a ``memoryview``
3003 instance and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01003004 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003005 self._no_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003006
3007
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003008 def test_memoryview_respects_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01003009 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003010 When called with a ``memoryview`` instance,
3011 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter
3012 and doesn't copy more than that number of bytes in.
Cory Benfield62d10332014-06-15 10:03:41 +01003013 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003014 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003015
3016
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003017 def test_memoryview_doesnt_overfill(self):
Cory Benfield62d10332014-06-15 10:03:41 +01003018 """
Jean-Paul Calderone8fd82552015-03-15 17:21:07 -04003019 When called with a ``memoryview`` instance,
3020 :py:obj:`Connection.recv_into` respects the size of the array and
3021 doesn't write more bytes into it than will fit.
Cory Benfield62d10332014-06-15 10:03:41 +01003022 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003023 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003024
3025
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003026 def test_memoryview_really_doesnt_overfill(self):
3027 """
3028 When called with a ``memoryview`` instance and an ``nbytes`` value
3029 that is too large, :py:obj:`Connection.recv_into` respects the size
3030 of the array and not the ``nbytes`` value and doesn't write more
3031 bytes into the buffer than will fit.
3032 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003033 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003034
3035
Cory Benfield62d10332014-06-15 10:03:41 +01003036
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003037class ConnectionSendallTests(TestCase, _LoopbackMixin):
3038 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003039 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003040 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003041 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003042 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003043 When called with arguments other than a string argument for its first
3044 parameter or with more than two arguments, :py:obj:`Connection.sendall`
3045 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003046 """
3047 connection = Connection(Context(TLSv1_METHOD), None)
3048 self.assertRaises(TypeError, connection.sendall)
3049 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003050 self.assertRaises(
3051 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003052
3053
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003054 def test_short(self):
3055 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003056 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003057 it.
3058 """
3059 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04003060 server.sendall(b('x'))
3061 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003062
3063
Abraham Martinef063482015-03-25 14:06:24 +00003064 def test_text(self):
3065 """
Jean-Paul Calderone93477422015-04-13 20:38:57 -04003066 :py:obj:`Connection.sendall` transmits all the content in the string
3067 passed to it raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003068 """
3069 server, client = self._loopback()
3070 with catch_warnings(record=True) as w:
3071 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003072 server.sendall(b"x".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003073 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003074 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003075 WARNING_TYPE_EXPECTED
3076 ),
3077 str(w[-1].message)
3078 )
3079 self.assertIs(w[-1].category, DeprecationWarning)
3080 self.assertEquals(client.recv(1), b"x")
Abraham Martinef063482015-03-25 14:06:24 +00003081
3082
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003083 try:
3084 memoryview
3085 except NameError:
3086 "cannot test sending memoryview without memoryview"
3087 else:
3088 def test_short_memoryview(self):
3089 """
3090 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003091 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003092 """
3093 server, client = self._loopback()
3094 server.sendall(memoryview(b('x')))
3095 self.assertEquals(client.recv(1), b('x'))
3096
3097
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003098 try:
3099 buffer
3100 except NameError:
3101 "cannot test sending buffers without buffers"
3102 else:
3103 def test_short_buffers(self):
3104 """
3105 When passed a buffer containing a small number of bytes,
3106 :py:obj:`Connection.sendall` transmits all of them.
3107 """
3108 server, client = self._loopback()
3109 server.sendall(buffer(b('x')))
3110 self.assertEquals(client.recv(1), b('x'))
3111
3112
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003113 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003114 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003115 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003116 it even if this requires multiple calls of an underlying write function.
3117 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003118 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003119 # Should be enough, underlying SSL_write should only do 16k at a time.
3120 # On Windows, after 32k of bytes the write will block (forever - because
3121 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04003122 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003123 server.sendall(message)
3124 accum = []
3125 received = 0
3126 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003127 data = client.recv(1024)
3128 accum.append(data)
3129 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04003130 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003131
3132
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003133 def test_closed(self):
3134 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003135 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003136 write error from the low level write call.
3137 """
3138 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003139 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003140 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003141 if platform == "win32":
3142 self.assertEqual(exc.args[0], ESHUTDOWN)
3143 else:
3144 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003145
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003146
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04003147
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003148class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
3149 """
3150 Tests for SSL renegotiation APIs.
3151 """
3152 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003153 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003154 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003155 arguments.
3156 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003157 connection = Connection(Context(TLSv1_METHOD), None)
3158 self.assertRaises(TypeError, connection.renegotiate, None)
3159
3160
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003161 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003162 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003163 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003164 any arguments.
3165 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003166 connection = Connection(Context(TLSv1_METHOD), None)
3167 self.assertRaises(TypeError, connection.total_renegotiations, None)
3168
3169
3170 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003171 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003172 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003173 renegotiations have happened.
3174 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003175 connection = Connection(Context(TLSv1_METHOD), None)
3176 self.assertEquals(connection.total_renegotiations(), 0)
3177
3178
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003179# def test_renegotiate(self):
3180# """
3181# """
3182# server, client = self._loopback()
3183
3184# server.send("hello world")
3185# self.assertEquals(client.recv(len("hello world")), "hello world")
3186
3187# self.assertEquals(server.total_renegotiations(), 0)
3188# self.assertTrue(server.renegotiate())
3189
3190# server.setblocking(False)
3191# client.setblocking(False)
3192# while server.renegotiate_pending():
3193# client.do_handshake()
3194# server.do_handshake()
3195
3196# self.assertEquals(server.total_renegotiations(), 1)
3197
3198
3199
3200
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003201class ErrorTests(TestCase):
3202 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003203 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003204 """
3205 def test_type(self):
3206 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003207 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003208 """
3209 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05003210 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05003211
3212
3213
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003214class ConstantsTests(TestCase):
3215 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003216 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003217
3218 These are values defined by OpenSSL intended only to be used as flags to
3219 OpenSSL APIs. The only assertions it seems can be made about them is
3220 their values.
3221 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003222 # unittest.TestCase has no skip mechanism
3223 if OP_NO_QUERY_MTU is not None:
3224 def test_op_no_query_mtu(self):
3225 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003226 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003227 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003228 """
3229 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
3230 else:
3231 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003232
3233
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003234 if OP_COOKIE_EXCHANGE is not None:
3235 def test_op_cookie_exchange(self):
3236 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003237 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003238 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003239 """
3240 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
3241 else:
3242 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003243
3244
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003245 if OP_NO_TICKET is not None:
3246 def test_op_no_ticket(self):
3247 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003248 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003249 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003250 """
3251 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04003252 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003253 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05003254
3255
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003256 if OP_NO_COMPRESSION is not None:
3257 def test_op_no_compression(self):
3258 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003259 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
3260 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003261 """
3262 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
3263 else:
3264 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3265
3266
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003267 def test_sess_cache_off(self):
3268 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003269 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3270 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003271 """
3272 self.assertEqual(0x0, SESS_CACHE_OFF)
3273
3274
3275 def test_sess_cache_client(self):
3276 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003277 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3278 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003279 """
3280 self.assertEqual(0x1, SESS_CACHE_CLIENT)
3281
3282
3283 def test_sess_cache_server(self):
3284 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003285 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3286 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003287 """
3288 self.assertEqual(0x2, SESS_CACHE_SERVER)
3289
3290
3291 def test_sess_cache_both(self):
3292 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003293 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3294 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003295 """
3296 self.assertEqual(0x3, SESS_CACHE_BOTH)
3297
3298
3299 def test_sess_cache_no_auto_clear(self):
3300 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003301 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3302 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3303 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003304 """
3305 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
3306
3307
3308 def test_sess_cache_no_internal_lookup(self):
3309 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003310 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3311 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3312 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003313 """
3314 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
3315
3316
3317 def test_sess_cache_no_internal_store(self):
3318 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003319 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3320 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3321 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003322 """
3323 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
3324
3325
3326 def test_sess_cache_no_internal(self):
3327 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003328 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3329 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
3330 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003331 """
3332 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
3333
3334
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04003335
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003336class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05003337 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003338 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003339 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003340 def _server(self, sock):
3341 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003342 Create a new server-side SSL :py:obj:`Connection` object wrapped around
3343 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003344 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003345 # Create the server side Connection. This is mostly setup boilerplate
3346 # - use TLSv1, use a particular certificate, etc.
3347 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003348 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
3349 server_ctx.set_verify(VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE, verify_cb)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003350 server_store = server_ctx.get_cert_store()
3351 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3352 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3353 server_ctx.check_privatekey()
3354 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003355 # Here the Connection is actually created. If None is passed as the 2nd
3356 # parameter, it indicates a memory BIO should be created.
3357 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003358 server_conn.set_accept_state()
3359 return server_conn
3360
3361
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003362 def _client(self, sock):
3363 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003364 Create a new client-side SSL :py:obj:`Connection` object wrapped around
3365 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003366 """
3367 # Now create the client side Connection. Similar boilerplate to the
3368 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003369 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003370 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
3371 client_ctx.set_verify(VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE, verify_cb)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003372 client_store = client_ctx.get_cert_store()
3373 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
3374 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
3375 client_ctx.check_privatekey()
3376 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003377 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003378 client_conn.set_connect_state()
3379 return client_conn
3380
3381
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003382 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003383 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003384 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003385 reading from the output of each and writing those bytes to the input of
3386 the other and in this way establish a connection and exchange
3387 application-level bytes with each other.
3388 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003389 server_conn = self._server(None)
3390 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003391
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003392 # There should be no key or nonces yet.
3393 self.assertIdentical(server_conn.master_key(), None)
3394 self.assertIdentical(server_conn.client_random(), None)
3395 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003396
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003397 # First, the handshake needs to happen. We'll deliver bytes back and
3398 # forth between the client and server until neither of them feels like
3399 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003400 self.assertIdentical(
3401 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003402
3403 # Now that the handshake is done, there should be a key and nonces.
3404 self.assertNotIdentical(server_conn.master_key(), None)
3405 self.assertNotIdentical(server_conn.client_random(), None)
3406 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04003407 self.assertEquals(server_conn.client_random(), client_conn.client_random())
3408 self.assertEquals(server_conn.server_random(), client_conn.server_random())
3409 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
3410 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003411
3412 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003413 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05003414
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003415 server_conn.write(important_message)
3416 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003417 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003418 (client_conn, important_message))
3419
3420 client_conn.write(important_message[::-1])
3421 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003422 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003423 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003424
3425
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003426 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003427 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003428 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003429
3430 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09003431 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003432 this test fails, there must be a problem outside the memory BIO
3433 code, as no memory BIO is involved here). Even though this isn't a
3434 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003435 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04003436 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003437
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003438 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05003439 client_conn.send(important_message)
3440 msg = server_conn.recv(1024)
3441 self.assertEqual(msg, important_message)
3442
3443 # Again in the other direction, just for fun.
3444 important_message = important_message[::-1]
3445 server_conn.send(important_message)
3446 msg = client_conn.recv(1024)
3447 self.assertEqual(msg, important_message)
3448
3449
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04003450 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003451 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003452 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
3453 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003454 """
3455 context = Context(SSLv3_METHOD)
3456 client = socket()
3457 clientSSL = Connection(context, client)
Alex Gaynor43307782015-09-04 09:05:45 -04003458 self.assertRaises(TypeError, clientSSL.bio_read, 100)
3459 self.assertRaises(TypeError, clientSSL.bio_write, "foo")
Alex Gaynor7e8b61e2015-09-04 13:13:05 -04003460 self.assertRaises(TypeError, clientSSL.bio_shutdown)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003461
3462
3463 def test_outgoingOverflow(self):
3464 """
3465 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09003466 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003467 returned and that many bytes from the beginning of the input can be
3468 read from the other end of the connection.
3469 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003470 server = self._server(None)
3471 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003472
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003473 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003474
3475 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003476 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003477 # Sanity check. We're trying to test what happens when the entire
3478 # input can't be sent. If the entire input was sent, this test is
3479 # meaningless.
3480 self.assertTrue(sent < size)
3481
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003482 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003483 self.assertIdentical(receiver, server)
3484
3485 # We can rely on all of these bytes being received at once because
3486 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
3487 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003488
3489
3490 def test_shutdown(self):
3491 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003492 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
3493 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003494 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003495 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003496 server.bio_shutdown()
3497 e = self.assertRaises(Error, server.recv, 1024)
3498 # We don't want WantReadError or ZeroReturnError or anything - it's a
3499 # handshake failure.
3500 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003501
3502
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003503 def test_unexpectedEndOfFile(self):
3504 """
3505 If the connection is lost before an orderly SSL shutdown occurs,
3506 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
3507 "Unexpected EOF".
3508 """
3509 server_conn, client_conn = self._loopback()
3510 client_conn.sock_shutdown(SHUT_RDWR)
3511 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
3512 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
3513
3514
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003515 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003516 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003517 Verify the return value of the :py:obj:`get_client_ca_list` method for server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003518
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003519 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003520 before the client and server are connected to each other. This
3521 function should specify a list of CAs for the server to send to the
3522 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09003523 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003524 times.
3525 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003526 server = self._server(None)
3527 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003528 self.assertEqual(client.get_client_ca_list(), [])
3529 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003530 ctx = server.get_context()
3531 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003532 self.assertEqual(client.get_client_ca_list(), [])
3533 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003534 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003535 self.assertEqual(client.get_client_ca_list(), expected)
3536 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003537
3538
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003539 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003540 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003541 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003542 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003543 """
3544 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003545 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
3546 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
3547 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003548
3549
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003550 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003551 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003552 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003553 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09003554 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003555 after the connection is set up.
3556 """
3557 def no_ca(ctx):
3558 ctx.set_client_ca_list([])
3559 return []
3560 self._check_client_ca_list(no_ca)
3561
3562
3563 def test_set_one_ca_list(self):
3564 """
3565 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003566 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003567 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003568 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003569 X509Name after the connection is set up.
3570 """
3571 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3572 cadesc = cacert.get_subject()
3573 def single_ca(ctx):
3574 ctx.set_client_ca_list([cadesc])
3575 return [cadesc]
3576 self._check_client_ca_list(single_ca)
3577
3578
3579 def test_set_multiple_ca_list(self):
3580 """
3581 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003582 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003583 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003584 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003585 X509Names after the connection is set up.
3586 """
3587 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3588 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3589
3590 sedesc = secert.get_subject()
3591 cldesc = clcert.get_subject()
3592
3593 def multiple_ca(ctx):
3594 L = [sedesc, cldesc]
3595 ctx.set_client_ca_list(L)
3596 return L
3597 self._check_client_ca_list(multiple_ca)
3598
3599
3600 def test_reset_ca_list(self):
3601 """
3602 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09003603 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003604 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003605 """
3606 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3607 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3608 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3609
3610 cadesc = cacert.get_subject()
3611 sedesc = secert.get_subject()
3612 cldesc = clcert.get_subject()
3613
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003614 def changed_ca(ctx):
3615 ctx.set_client_ca_list([sedesc, cldesc])
3616 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003617 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003618 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003619
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003620
3621 def test_mutated_ca_list(self):
3622 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003623 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003624 afterwards, this does not affect the list of CA names sent to the
3625 client.
3626 """
3627 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3628 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3629
3630 cadesc = cacert.get_subject()
3631 sedesc = secert.get_subject()
3632
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003633 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003634 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003635 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003636 L.append(sedesc)
3637 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003638 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003639
3640
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003641 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003642 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003643 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003644 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003645 """
3646 ctx = Context(TLSv1_METHOD)
3647 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003648 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003649 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003650 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003651
3652
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003653 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003654 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003655 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09003656 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003657 """
3658 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3659 cadesc = cacert.get_subject()
3660 def single_ca(ctx):
3661 ctx.add_client_ca(cacert)
3662 return [cadesc]
3663 self._check_client_ca_list(single_ca)
3664
3665
3666 def test_multiple_add_client_ca(self):
3667 """
3668 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09003669 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003670 """
3671 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3672 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3673
3674 cadesc = cacert.get_subject()
3675 sedesc = secert.get_subject()
3676
3677 def multiple_ca(ctx):
3678 ctx.add_client_ca(cacert)
3679 ctx.add_client_ca(secert)
3680 return [cadesc, sedesc]
3681 self._check_client_ca_list(multiple_ca)
3682
3683
3684 def test_set_and_add_client_ca(self):
3685 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003686 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
3687 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003688 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003689 """
3690 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3691 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3692 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3693
3694 cadesc = cacert.get_subject()
3695 sedesc = secert.get_subject()
3696 cldesc = clcert.get_subject()
3697
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003698 def mixed_set_add_ca(ctx):
3699 ctx.set_client_ca_list([cadesc, sedesc])
3700 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003701 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003702 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003703
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003704
3705 def test_set_after_add_client_ca(self):
3706 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003707 A call to :py:obj:`Context.set_client_ca_list` after a call to
3708 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003709 call with the names specified by the latter cal.
3710 """
3711 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3712 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3713 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3714
3715 cadesc = cacert.get_subject()
3716 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003717
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003718 def set_replaces_add_ca(ctx):
3719 ctx.add_client_ca(clcert)
3720 ctx.set_client_ca_list([cadesc])
3721 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003722 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003723 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003724
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003725
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003726
3727class ConnectionBIOTests(TestCase):
3728 """
3729 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3730 """
3731 def test_wantReadError(self):
3732 """
3733 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
3734 if there are no bytes available to be read from the BIO.
3735 """
3736 ctx = Context(TLSv1_METHOD)
3737 conn = Connection(ctx, None)
3738 self.assertRaises(WantReadError, conn.bio_read, 1024)
3739
3740
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003741 def test_buffer_size(self):
3742 """
3743 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3744 number of bytes to read and return.
3745 """
3746 ctx = Context(TLSv1_METHOD)
3747 conn = Connection(ctx, None)
3748 conn.set_connect_state()
3749 try:
3750 conn.do_handshake()
3751 except WantReadError:
3752 pass
3753 data = conn.bio_read(2)
3754 self.assertEqual(2, len(data))
3755
3756
3757 if not PY3:
3758 def test_buffer_size_long(self):
3759 """
3760 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3761 :py:obj:`long` as well as :py:obj:`int`.
3762 """
3763 ctx = Context(TLSv1_METHOD)
3764 conn = Connection(ctx, None)
3765 conn.set_connect_state()
3766 try:
3767 conn.do_handshake()
3768 except WantReadError:
3769 pass
3770 data = conn.bio_read(long(2))
3771 self.assertEqual(2, len(data))
3772
3773
3774
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003775
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003776class InfoConstantTests(TestCase):
3777 """
3778 Tests for assorted constants exposed for use in info callbacks.
3779 """
3780 def test_integers(self):
3781 """
3782 All of the info constants are integers.
3783
3784 This is a very weak test. It would be nice to have one that actually
3785 verifies that as certain info events happen, the value passed to the
3786 info callback matches up with the constant exposed by OpenSSL.SSL.
3787 """
3788 for const in [
3789 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3790 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3791 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3792 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3793 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
3794 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
3795
3796 self.assertTrue(isinstance(const, int))
3797
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003798
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003799if __name__ == '__main__':
3800 main()