blob: 2fef3068af00ed218ab1a61ba442fc9fb2925fef [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
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001071 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 """
2157
2158 def attr_access_test(connection):
2159 return connection.an_attribute_which_is_not_defined
2160
2161 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)
2172 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04002173 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002174
2175
2176 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002177 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002178 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002179 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002180 port = socket()
2181 port.bind(('', 0))
2182 port.listen(3)
2183
2184 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002185 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2186 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002187
2188
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002189 if platform == "darwin":
2190 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2191 else:
2192 def test_connect_ex(self):
2193 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002194 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002195 errno instead of raising an exception.
2196 """
2197 port = socket()
2198 port.bind(('', 0))
2199 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002200
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002201 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2202 clientSSL.setblocking(False)
2203 result = clientSSL.connect_ex(port.getsockname())
2204 expected = (EINPROGRESS, EWOULDBLOCK)
2205 self.assertTrue(
2206 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002207
2208
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002209 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002210 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002211 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002212 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002213 connection = Connection(Context(TLSv1_METHOD), socket())
2214 self.assertRaises(TypeError, connection.accept, None)
2215
2216
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002217 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002218 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002219 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
2220 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002221 connection originated from.
2222 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002223 ctx = Context(TLSv1_METHOD)
2224 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2225 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002226 port = socket()
2227 portSSL = Connection(ctx, port)
2228 portSSL.bind(('', 0))
2229 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002230
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002231 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002232
2233 # Calling portSSL.getsockname() here to get the server IP address sounds
2234 # great, but frequently fails on Windows.
2235 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002236
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002237 serverSSL, address = portSSL.accept()
2238
2239 self.assertTrue(isinstance(serverSSL, Connection))
2240 self.assertIdentical(serverSSL.get_context(), ctx)
2241 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002242
2243
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002244 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002245 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002246 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002247 number of arguments or with arguments other than integers.
2248 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002249 connection = Connection(Context(TLSv1_METHOD), None)
2250 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04002251 self.assertRaises(TypeError, connection.get_shutdown, None)
2252 self.assertRaises(TypeError, connection.set_shutdown)
2253 self.assertRaises(TypeError, connection.set_shutdown, None)
2254 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002255
2256
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002257 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002258 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002259 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002260 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002261 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002262 self.assertFalse(server.shutdown())
2263 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002264 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002265 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
2266 client.shutdown()
Alex Gaynor43307782015-09-04 09:05:45 -04002267 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002268 self.assertRaises(ZeroReturnError, server.recv, 1024)
Alex Gaynor43307782015-09-04 09:05:45 -04002269 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002270
2271
Paul Aurichc85e0862015-01-08 08:34:33 -08002272 def test_shutdown_closed(self):
2273 """
2274 If the underlying socket is closed, :py:obj:`Connection.shutdown` propagates the
2275 write error from the low level write call.
2276 """
2277 server, client = self._loopback()
2278 server.sock_shutdown(2)
2279 exc = self.assertRaises(SysCallError, server.shutdown)
2280 if platform == "win32":
2281 self.assertEqual(exc.args[0], ESHUTDOWN)
2282 else:
2283 self.assertEqual(exc.args[0], EPIPE)
2284
2285
Glyph89389472015-04-14 17:29:26 -04002286 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002287 """
Glyph89389472015-04-14 17:29:26 -04002288 If the underlying connection is truncated, :obj:`Connection.shutdown`
2289 raises an :obj:`Error`.
Glyph6064ec32015-04-14 16:38:22 -04002290 """
Glyph89389472015-04-14 17:29:26 -04002291 server_ctx = Context(TLSv1_METHOD)
2292 client_ctx = Context(TLSv1_METHOD)
2293 server_ctx.use_privatekey(
2294 load_privatekey(FILETYPE_PEM, server_key_pem))
2295 server_ctx.use_certificate(
2296 load_certificate(FILETYPE_PEM, server_cert_pem))
2297 server = Connection(server_ctx, None)
2298 client = Connection(client_ctx, None)
2299 self._handshakeInMemory(client, server)
2300 self.assertEqual(server.shutdown(), False)
2301 self.assertRaises(WantReadError, server.shutdown)
2302 server.bio_shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002303 self.assertRaises(Error, server.shutdown)
2304
2305
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002306 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002307 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002308 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002309 process.
2310 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002311 connection = Connection(Context(TLSv1_METHOD), socket())
2312 connection.set_shutdown(RECEIVED_SHUTDOWN)
2313 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2314
2315
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002316 if not PY3:
2317 def test_set_shutdown_long(self):
2318 """
2319 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
2320 of type :py:obj:`long` as well as :py:obj:`int`.
2321 """
2322 connection = Connection(Context(TLSv1_METHOD), socket())
2323 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
2324 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2325
2326
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002327 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002328 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002329 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
2330 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002331 with any arguments.
2332 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002333 conn = Connection(Context(TLSv1_METHOD), None)
2334 self.assertRaises(TypeError, conn.get_app_data, None)
2335 self.assertRaises(TypeError, conn.set_app_data)
2336 self.assertRaises(TypeError, conn.set_app_data, None, None)
2337
2338
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002339 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002340 """
2341 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002342 :py:obj:`Connection.set_app_data` and later retrieved with
2343 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002344 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002345 conn = Connection(Context(TLSv1_METHOD), None)
2346 app_data = object()
2347 conn.set_app_data(app_data)
2348 self.assertIdentical(conn.get_app_data(), app_data)
2349
2350
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002351 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002352 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002353 :py:obj:`Connection.makefile` is not implemented and calling that method raises
2354 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002355 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002356 conn = Connection(Context(TLSv1_METHOD), None)
2357 self.assertRaises(NotImplementedError, conn.makefile)
2358
2359
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002360 def test_get_peer_cert_chain_wrong_args(self):
2361 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002362 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002363 arguments.
2364 """
2365 conn = Connection(Context(TLSv1_METHOD), None)
2366 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
2367 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
2368 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
2369 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
2370
2371
2372 def test_get_peer_cert_chain(self):
2373 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002374 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002375 the connected server returned for the certification verification.
2376 """
2377 chain = _create_certificate_chain()
2378 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2379
2380 serverContext = Context(TLSv1_METHOD)
2381 serverContext.use_privatekey(skey)
2382 serverContext.use_certificate(scert)
2383 serverContext.add_extra_chain_cert(icert)
2384 serverContext.add_extra_chain_cert(cacert)
2385 server = Connection(serverContext, None)
2386 server.set_accept_state()
2387
2388 # Create the client
2389 clientContext = Context(TLSv1_METHOD)
2390 clientContext.set_verify(VERIFY_NONE, verify_cb)
2391 client = Connection(clientContext, None)
2392 client.set_connect_state()
2393
2394 self._interactInMemory(client, server)
2395
2396 chain = client.get_peer_cert_chain()
2397 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002398 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002399 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002400 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002401 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002402 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002403 "Authority Certificate", chain[2].get_subject().CN)
2404
2405
2406 def test_get_peer_cert_chain_none(self):
2407 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002408 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002409 certificate chain.
2410 """
2411 ctx = Context(TLSv1_METHOD)
2412 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2413 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2414 server = Connection(ctx, None)
2415 server.set_accept_state()
2416 client = Connection(Context(TLSv1_METHOD), None)
2417 client.set_connect_state()
2418 self._interactInMemory(client, server)
2419 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002420
2421
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002422 def test_get_session_wrong_args(self):
2423 """
2424 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
2425 with any arguments.
2426 """
2427 ctx = Context(TLSv1_METHOD)
2428 server = Connection(ctx, None)
2429 self.assertRaises(TypeError, server.get_session, 123)
2430 self.assertRaises(TypeError, server.get_session, "hello")
2431 self.assertRaises(TypeError, server.get_session, object())
2432
2433
2434 def test_get_session_unconnected(self):
2435 """
2436 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
2437 an object which has not been connected.
2438 """
2439 ctx = Context(TLSv1_METHOD)
2440 server = Connection(ctx, None)
2441 session = server.get_session()
2442 self.assertIdentical(None, session)
2443
2444
2445 def test_server_get_session(self):
2446 """
2447 On the server side of a connection, :py:obj:`Connection.get_session`
2448 returns a :py:class:`Session` instance representing the SSL session for
2449 that connection.
2450 """
2451 server, client = self._loopback()
2452 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002453 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002454
2455
2456 def test_client_get_session(self):
2457 """
2458 On the client side of a connection, :py:obj:`Connection.get_session`
2459 returns a :py:class:`Session` instance representing the SSL session for
2460 that connection.
2461 """
2462 server, client = self._loopback()
2463 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002464 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002465
2466
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002467 def test_set_session_wrong_args(self):
2468 """
2469 If called with an object that is not an instance of :py:class:`Session`,
2470 or with other than one argument, :py:obj:`Connection.set_session` raises
2471 :py:obj:`TypeError`.
2472 """
2473 ctx = Context(TLSv1_METHOD)
2474 connection = Connection(ctx, None)
2475 self.assertRaises(TypeError, connection.set_session)
2476 self.assertRaises(TypeError, connection.set_session, 123)
2477 self.assertRaises(TypeError, connection.set_session, "hello")
2478 self.assertRaises(TypeError, connection.set_session, object())
2479 self.assertRaises(
2480 TypeError, connection.set_session, Session(), Session())
2481
2482
2483 def test_client_set_session(self):
2484 """
2485 :py:obj:`Connection.set_session`, when used prior to a connection being
2486 established, accepts a :py:class:`Session` instance and causes an
2487 attempt to re-use the session it represents when the SSL handshake is
2488 performed.
2489 """
2490 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2491 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2492 ctx = Context(TLSv1_METHOD)
2493 ctx.use_privatekey(key)
2494 ctx.use_certificate(cert)
2495 ctx.set_session_id("unity-test")
2496
2497 def makeServer(socket):
2498 server = Connection(ctx, socket)
2499 server.set_accept_state()
2500 return server
2501
2502 originalServer, originalClient = self._loopback(
2503 serverFactory=makeServer)
2504 originalSession = originalClient.get_session()
2505
2506 def makeClient(socket):
2507 client = self._loopbackClientFactory(socket)
2508 client.set_session(originalSession)
2509 return client
2510 resumedServer, resumedClient = self._loopback(
2511 serverFactory=makeServer,
2512 clientFactory=makeClient)
2513
2514 # This is a proxy: in general, we have no access to any unique
2515 # identifier for the session (new enough versions of OpenSSL expose a
2516 # hash which could be usable, but "new enough" is very, very new).
2517 # Instead, exploit the fact that the master key is re-used if the
2518 # session is re-used. As long as the master key for the two connections
2519 # is the same, the session was re-used!
2520 self.assertEqual(
2521 originalServer.master_key(), resumedServer.master_key())
2522
2523
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002524 def test_set_session_wrong_method(self):
2525 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002526 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
2527 instance associated with a context using a different SSL method than the
2528 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
2529 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002530 """
2531 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2532 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2533 ctx = Context(TLSv1_METHOD)
2534 ctx.use_privatekey(key)
2535 ctx.use_certificate(cert)
2536 ctx.set_session_id("unity-test")
2537
2538 def makeServer(socket):
2539 server = Connection(ctx, socket)
2540 server.set_accept_state()
2541 return server
2542
2543 originalServer, originalClient = self._loopback(
2544 serverFactory=makeServer)
2545 originalSession = originalClient.get_session()
2546
2547 def makeClient(socket):
2548 # Intentionally use a different, incompatible method here.
2549 client = Connection(Context(SSLv3_METHOD), socket)
2550 client.set_connect_state()
2551 client.set_session(originalSession)
2552 return client
2553
2554 self.assertRaises(
2555 Error,
2556 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2557
2558
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002559 def test_wantWriteError(self):
2560 """
2561 :py:obj:`Connection` methods which generate output raise
2562 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2563 fail indicating a should-write state.
2564 """
2565 client_socket, server_socket = socket_pair()
2566 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002567 # anything. Only write a single byte at a time so we can be sure we
2568 # completely fill the buffer. Even though the socket API is allowed to
2569 # signal a short write via its return value it seems this doesn't
2570 # always happen on all platforms (FreeBSD and OS X particular) for the
2571 # very last bit of available buffer space.
2572 msg = b"x"
2573 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002574 try:
2575 client_socket.send(msg)
2576 except error as e:
2577 if e.errno == EWOULDBLOCK:
2578 break
2579 raise
2580 else:
2581 self.fail(
2582 "Failed to fill socket buffer, cannot test BIO want write")
2583
2584 ctx = Context(TLSv1_METHOD)
2585 conn = Connection(ctx, client_socket)
2586 # Client's speak first, so make it an SSL client
2587 conn.set_connect_state()
2588 self.assertRaises(WantWriteError, conn.do_handshake)
2589
2590 # XXX want_read
2591
Fedor Brunner416f4a12014-03-28 13:18:38 +01002592 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002593 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002594 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2595 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002596 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002597 ctx = Context(TLSv1_METHOD)
2598 connection = Connection(ctx, None)
2599 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002600
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002601
Fedor Brunner416f4a12014-03-28 13:18:38 +01002602 def test_get_peer_finished_before_connect(self):
2603 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002604 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2605 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002606 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002607 ctx = Context(TLSv1_METHOD)
2608 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002609 self.assertEqual(connection.get_peer_finished(), None)
2610
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002611
Fedor Brunner416f4a12014-03-28 13:18:38 +01002612 def test_get_finished(self):
2613 """
2614 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002615 message send from client, or server. Finished messages are send during
2616 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002617 """
2618
Fedor Brunner5747b932014-03-05 14:22:34 +01002619 server, client = self._loopback()
2620
2621 self.assertNotEqual(server.get_finished(), None)
2622 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002623
Jean-Paul Calderoned979f232014-03-30 11:58:00 -04002624
Fedor Brunner416f4a12014-03-28 13:18:38 +01002625 def test_get_peer_finished(self):
2626 """
2627 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002628 message received from client, or server. Finished messages are send
2629 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002630 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002631 server, client = self._loopback()
2632
2633 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002634 self.assertTrue(len(server.get_peer_finished()) > 0)
2635
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002636
Fedor Brunner416f4a12014-03-28 13:18:38 +01002637 def test_tls_finished_message_symmetry(self):
2638 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002639 The TLS Finished message send by server must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002640 received by client.
2641
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002642 The TLS Finished message send by client must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002643 received by server.
2644 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002645 server, client = self._loopback()
2646
Fedor Brunner5747b932014-03-05 14:22:34 +01002647 self.assertEqual(server.get_finished(), client.get_peer_finished())
2648 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002649
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002650
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002651 def test_get_cipher_name_before_connect(self):
2652 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002653 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2654 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002655 """
2656 ctx = Context(TLSv1_METHOD)
2657 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002658 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002659
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002660
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002661 def test_get_cipher_name(self):
2662 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002663 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2664 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002665 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002666 server, client = self._loopback()
2667 server_cipher_name, client_cipher_name = \
2668 server.get_cipher_name(), client.get_cipher_name()
2669
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002670 self.assertIsInstance(server_cipher_name, text_type)
2671 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002672
2673 self.assertEqual(server_cipher_name, client_cipher_name)
2674
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002675
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002676 def test_get_cipher_version_before_connect(self):
2677 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002678 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2679 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002680 """
2681 ctx = Context(TLSv1_METHOD)
2682 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002683 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002684
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002685
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002686 def test_get_cipher_version(self):
2687 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002688 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2689 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002690 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002691 server, client = self._loopback()
2692 server_cipher_version, client_cipher_version = \
2693 server.get_cipher_version(), client.get_cipher_version()
2694
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002695 self.assertIsInstance(server_cipher_version, text_type)
2696 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002697
2698 self.assertEqual(server_cipher_version, client_cipher_version)
2699
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002700
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002701 def test_get_cipher_bits_before_connect(self):
2702 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002703 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2704 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002705 """
2706 ctx = Context(TLSv1_METHOD)
2707 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002708 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002709
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002710
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002711 def test_get_cipher_bits(self):
2712 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002713 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2714 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002715 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002716 server, client = self._loopback()
2717 server_cipher_bits, client_cipher_bits = \
2718 server.get_cipher_bits(), client.get_cipher_bits()
2719
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002720 self.assertIsInstance(server_cipher_bits, int)
2721 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002722
2723 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002724
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002725
Jim Shaverabff1882015-05-27 09:15:55 -04002726 def test_get_protocol_version_name(self):
2727 """
2728 :py:obj:`Connection.get_protocol_version_name()` returns a string
2729 giving the protocol version of the current connection.
2730 """
2731 server, client = self._loopback()
2732 client_protocol_version_name = client.get_protocol_version_name()
2733 server_protocol_version_name = server.get_protocol_version_name()
2734
Jim Shaver58d25732015-05-28 11:52:32 -04002735 self.assertIsInstance(server_protocol_version_name, text_type)
2736 self.assertIsInstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002737
2738 self.assertEqual(server_protocol_version_name, client_protocol_version_name)
2739
2740
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002741 def test_get_protocol_version(self):
2742 """
Alex Gaynor43307782015-09-04 09:05:45 -04002743 :py:obj:`Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002744 giving the protocol version of the current connection.
2745 """
2746 server, client = self._loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002747 client_protocol_version = client.get_protocol_version()
2748 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002749
Jim Shaverabff1882015-05-27 09:15:55 -04002750 self.assertIsInstance(server_protocol_version, int)
2751 self.assertIsInstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002752
2753 self.assertEqual(server_protocol_version, client_protocol_version)
2754
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002755
Jim Shaver208438c2015-05-28 09:52:38 -04002756
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002757class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002758 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002759 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002760 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002761 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002762 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002763 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002764 arguments.
2765 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002766 connection = Connection(Context(TLSv1_METHOD), None)
2767 self.assertRaises(TypeError, connection.get_cipher_list, None)
2768
2769
2770 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002771 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002772 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2773 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002774 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002775 connection = Connection(Context(TLSv1_METHOD), None)
2776 ciphers = connection.get_cipher_list()
2777 self.assertTrue(isinstance(ciphers, list))
2778 for cipher in ciphers:
2779 self.assertTrue(isinstance(cipher, str))
2780
2781
2782
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002783class ConnectionSendTests(TestCase, _LoopbackMixin):
2784 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002785 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002786 """
2787 def test_wrong_args(self):
2788 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002789 When called with arguments other than string argument for its first
2790 parameter or more than two arguments, :py:obj:`Connection.send` raises
2791 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002792 """
2793 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002794 self.assertRaises(TypeError, connection.send)
2795 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002796 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002797
2798
2799 def test_short_bytes(self):
2800 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002801 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002802 and returns the number of bytes sent.
2803 """
2804 server, client = self._loopback()
2805 count = server.send(b('xy'))
2806 self.assertEquals(count, 2)
2807 self.assertEquals(client.recv(2), b('xy'))
2808
Abraham Martinef063482015-03-25 14:06:24 +00002809
2810 def test_text(self):
2811 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002812 When passed a text, :py:obj:`Connection.send` transmits all of it and
2813 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002814 """
2815 server, client = self._loopback()
2816 with catch_warnings(record=True) as w:
2817 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002818 count = server.send(b"xy".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002819 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002820 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002821 WARNING_TYPE_EXPECTED
2822 ),
2823 str(w[-1].message)
2824 )
2825 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinef063482015-03-25 14:06:24 +00002826 self.assertEquals(count, 2)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002827 self.assertEquals(client.recv(2), b"xy")
Abraham Martinef063482015-03-25 14:06:24 +00002828
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002829 try:
2830 memoryview
2831 except NameError:
2832 "cannot test sending memoryview without memoryview"
2833 else:
2834 def test_short_memoryview(self):
2835 """
2836 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002837 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002838 bytes sent.
2839 """
2840 server, client = self._loopback()
2841 count = server.send(memoryview(b('xy')))
2842 self.assertEquals(count, 2)
2843 self.assertEquals(client.recv(2), b('xy'))
2844
2845
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002846 try:
2847 buffer
2848 except NameError:
2849 "cannot test sending buffer without buffer"
2850 else:
2851 def test_short_buffer(self):
2852 """
2853 When passed a buffer containing a small number of bytes,
2854 :py:obj:`Connection.send` transmits all of them and returns the number of
2855 bytes sent.
2856 """
2857 server, client = self._loopback()
2858 count = server.send(buffer(b('xy')))
2859 self.assertEquals(count, 2)
2860 self.assertEquals(client.recv(2), b('xy'))
2861
2862
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002863
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002864def _make_memoryview(size):
2865 """
2866 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2867 size.
2868 """
2869 return memoryview(bytearray(size))
2870
2871
2872
Cory Benfield62d10332014-06-15 10:03:41 +01002873class ConnectionRecvIntoTests(TestCase, _LoopbackMixin):
2874 """
2875 Tests for :py:obj:`Connection.recv_into`
2876 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002877 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002878 """
2879 Assert that when the given buffer is passed to
2880 ``Connection.recv_into``, whatever bytes are available to be received
2881 that fit into that buffer are written into that buffer.
2882 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002883 output_buffer = factory(5)
2884
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002885 server, client = self._loopback()
2886 server.send(b('xy'))
2887
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002888 self.assertEqual(client.recv_into(output_buffer), 2)
2889 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002890
2891
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002892 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002893 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002894 :py:obj:`Connection.recv_into` can be passed a ``bytearray`` instance
2895 and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002896 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002897 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002898
2899
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002900 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002901 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002902 Assert that when the given buffer is passed to ``Connection.recv_into``
2903 along with a value for ``nbytes`` that is less than the size of that
2904 buffer, only ``nbytes`` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002905 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002906 output_buffer = factory(10)
2907
Cory Benfield62d10332014-06-15 10:03:41 +01002908 server, client = self._loopback()
2909 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002910
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002911 self.assertEqual(client.recv_into(output_buffer, 5), 5)
2912 self.assertEqual(
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002913 output_buffer, bytearray(b('abcde\x00\x00\x00\x00\x00'))
2914 )
2915
2916
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002917 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002918 """
2919 When called with a ``bytearray`` instance,
2920 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter and
2921 doesn't copy in more than that number of bytes.
2922 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002923 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002924
2925
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002926 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002927 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002928 Assert that if there are more bytes available to be read from the
2929 receive buffer than would fit into the buffer passed to
2930 :py:obj:`Connection.recv_into`, only as many as fit are written into
2931 it.
Cory Benfield62d10332014-06-15 10:03:41 +01002932 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002933 output_buffer = factory(5)
2934
Cory Benfield62d10332014-06-15 10:03:41 +01002935 server, client = self._loopback()
2936 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002937
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002938 self.assertEqual(client.recv_into(output_buffer), 5)
2939 self.assertEqual(output_buffer, bytearray(b('abcde')))
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002940 rest = client.recv(5)
2941 self.assertEqual(b('fghij'), rest)
2942
2943
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002944 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002945 """
2946 When called with a ``bytearray`` instance,
2947 :py:obj:`Connection.recv_into` respects the size of the array and
2948 doesn't write more bytes into it than will fit.
2949 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002950 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002951
2952
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002953 def _really_doesnt_overfill_test(self, factory):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002954 """
2955 Assert that if the value given by ``nbytes`` is greater than the actual
2956 size of the output buffer passed to :py:obj:`Connection.recv_into`, the
2957 behavior is as if no value was given for ``nbytes`` at all.
2958 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002959 output_buffer = factory(5)
2960
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002961 server, client = self._loopback()
2962 server.send(b('abcdefghij'))
2963
2964 self.assertEqual(client.recv_into(output_buffer, 50), 5)
2965 self.assertEqual(output_buffer, bytearray(b('abcde')))
2966 rest = client.recv(5)
2967 self.assertEqual(b('fghij'), rest)
2968
2969
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002970 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002971 """
2972 When called with a ``bytearray`` instance and an ``nbytes`` value that
2973 is too large, :py:obj:`Connection.recv_into` respects the size of the
2974 array and not the ``nbytes`` value and doesn't write more bytes into
2975 the buffer than will fit.
2976 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002977 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002978
2979
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002980 def test_peek(self):
2981
2982 server, client = self._loopback()
2983 server.send(b('xy'))
2984
2985 for _ in range(2):
2986 output_buffer = bytearray(5)
2987 self.assertEqual(client.recv_into(output_buffer, flags=MSG_PEEK), 2)
2988 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
2989
2990
Cory Benfield62d10332014-06-15 10:03:41 +01002991 try:
2992 memoryview
2993 except NameError:
2994 "cannot test recv_into memoryview without memoryview"
2995 else:
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002996 def test_memoryview_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002997 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002998 :py:obj:`Connection.recv_into` can be passed a ``memoryview``
2999 instance and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01003000 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003001 self._no_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003002
3003
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003004 def test_memoryview_respects_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01003005 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003006 When called with a ``memoryview`` instance,
3007 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter
3008 and doesn't copy more than that number of bytes in.
Cory Benfield62d10332014-06-15 10:03:41 +01003009 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003010 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003011
3012
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003013 def test_memoryview_doesnt_overfill(self):
Cory Benfield62d10332014-06-15 10:03:41 +01003014 """
Jean-Paul Calderone8fd82552015-03-15 17:21:07 -04003015 When called with a ``memoryview`` instance,
3016 :py:obj:`Connection.recv_into` respects the size of the array and
3017 doesn't write more bytes into it than will fit.
Cory Benfield62d10332014-06-15 10:03:41 +01003018 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003019 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003020
3021
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003022 def test_memoryview_really_doesnt_overfill(self):
3023 """
3024 When called with a ``memoryview`` instance and an ``nbytes`` value
3025 that is too large, :py:obj:`Connection.recv_into` respects the size
3026 of the array and not the ``nbytes`` value and doesn't write more
3027 bytes into the buffer than will fit.
3028 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003029 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003030
3031
Cory Benfield62d10332014-06-15 10:03:41 +01003032
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003033class ConnectionSendallTests(TestCase, _LoopbackMixin):
3034 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003035 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003036 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003037 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003038 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003039 When called with arguments other than a string argument for its first
3040 parameter or with more than two arguments, :py:obj:`Connection.sendall`
3041 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003042 """
3043 connection = Connection(Context(TLSv1_METHOD), None)
3044 self.assertRaises(TypeError, connection.sendall)
3045 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003046 self.assertRaises(
3047 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003048
3049
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003050 def test_short(self):
3051 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003052 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003053 it.
3054 """
3055 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04003056 server.sendall(b('x'))
3057 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003058
3059
Abraham Martinef063482015-03-25 14:06:24 +00003060 def test_text(self):
3061 """
Jean-Paul Calderone93477422015-04-13 20:38:57 -04003062 :py:obj:`Connection.sendall` transmits all the content in the string
3063 passed to it raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003064 """
3065 server, client = self._loopback()
3066 with catch_warnings(record=True) as w:
3067 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003068 server.sendall(b"x".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003069 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003070 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003071 WARNING_TYPE_EXPECTED
3072 ),
3073 str(w[-1].message)
3074 )
3075 self.assertIs(w[-1].category, DeprecationWarning)
3076 self.assertEquals(client.recv(1), b"x")
Abraham Martinef063482015-03-25 14:06:24 +00003077
3078
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003079 try:
3080 memoryview
3081 except NameError:
3082 "cannot test sending memoryview without memoryview"
3083 else:
3084 def test_short_memoryview(self):
3085 """
3086 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003087 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003088 """
3089 server, client = self._loopback()
3090 server.sendall(memoryview(b('x')))
3091 self.assertEquals(client.recv(1), b('x'))
3092
3093
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003094 try:
3095 buffer
3096 except NameError:
3097 "cannot test sending buffers without buffers"
3098 else:
3099 def test_short_buffers(self):
3100 """
3101 When passed a buffer containing a small number of bytes,
3102 :py:obj:`Connection.sendall` transmits all of them.
3103 """
3104 server, client = self._loopback()
3105 server.sendall(buffer(b('x')))
3106 self.assertEquals(client.recv(1), b('x'))
3107
3108
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003109 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003110 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003111 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003112 it even if this requires multiple calls of an underlying write function.
3113 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003114 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003115 # Should be enough, underlying SSL_write should only do 16k at a time.
3116 # On Windows, after 32k of bytes the write will block (forever - because
3117 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04003118 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003119 server.sendall(message)
3120 accum = []
3121 received = 0
3122 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003123 data = client.recv(1024)
3124 accum.append(data)
3125 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04003126 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003127
3128
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003129 def test_closed(self):
3130 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003131 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003132 write error from the low level write call.
3133 """
3134 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003135 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003136 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003137 if platform == "win32":
3138 self.assertEqual(exc.args[0], ESHUTDOWN)
3139 else:
3140 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003141
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003142
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04003143
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003144class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
3145 """
3146 Tests for SSL renegotiation APIs.
3147 """
3148 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003149 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003150 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003151 arguments.
3152 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003153 connection = Connection(Context(TLSv1_METHOD), None)
3154 self.assertRaises(TypeError, connection.renegotiate, None)
3155
3156
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003157 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003158 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003159 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003160 any arguments.
3161 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003162 connection = Connection(Context(TLSv1_METHOD), None)
3163 self.assertRaises(TypeError, connection.total_renegotiations, None)
3164
3165
3166 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003167 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003168 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003169 renegotiations have happened.
3170 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003171 connection = Connection(Context(TLSv1_METHOD), None)
3172 self.assertEquals(connection.total_renegotiations(), 0)
3173
3174
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003175# def test_renegotiate(self):
3176# """
3177# """
3178# server, client = self._loopback()
3179
3180# server.send("hello world")
3181# self.assertEquals(client.recv(len("hello world")), "hello world")
3182
3183# self.assertEquals(server.total_renegotiations(), 0)
3184# self.assertTrue(server.renegotiate())
3185
3186# server.setblocking(False)
3187# client.setblocking(False)
3188# while server.renegotiate_pending():
3189# client.do_handshake()
3190# server.do_handshake()
3191
3192# self.assertEquals(server.total_renegotiations(), 1)
3193
3194
3195
3196
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003197class ErrorTests(TestCase):
3198 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003199 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003200 """
3201 def test_type(self):
3202 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003203 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003204 """
3205 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05003206 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05003207
3208
3209
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003210class ConstantsTests(TestCase):
3211 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003212 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003213
3214 These are values defined by OpenSSL intended only to be used as flags to
3215 OpenSSL APIs. The only assertions it seems can be made about them is
3216 their values.
3217 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003218 # unittest.TestCase has no skip mechanism
3219 if OP_NO_QUERY_MTU is not None:
3220 def test_op_no_query_mtu(self):
3221 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003222 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003223 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003224 """
3225 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
3226 else:
3227 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003228
3229
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003230 if OP_COOKIE_EXCHANGE is not None:
3231 def test_op_cookie_exchange(self):
3232 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003233 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003234 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003235 """
3236 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
3237 else:
3238 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003239
3240
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003241 if OP_NO_TICKET is not None:
3242 def test_op_no_ticket(self):
3243 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003244 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003245 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003246 """
3247 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04003248 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003249 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05003250
3251
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003252 if OP_NO_COMPRESSION is not None:
3253 def test_op_no_compression(self):
3254 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003255 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
3256 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003257 """
3258 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
3259 else:
3260 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3261
3262
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003263 def test_sess_cache_off(self):
3264 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003265 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3266 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003267 """
3268 self.assertEqual(0x0, SESS_CACHE_OFF)
3269
3270
3271 def test_sess_cache_client(self):
3272 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003273 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3274 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003275 """
3276 self.assertEqual(0x1, SESS_CACHE_CLIENT)
3277
3278
3279 def test_sess_cache_server(self):
3280 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003281 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3282 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003283 """
3284 self.assertEqual(0x2, SESS_CACHE_SERVER)
3285
3286
3287 def test_sess_cache_both(self):
3288 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003289 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3290 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003291 """
3292 self.assertEqual(0x3, SESS_CACHE_BOTH)
3293
3294
3295 def test_sess_cache_no_auto_clear(self):
3296 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003297 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3298 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3299 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003300 """
3301 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
3302
3303
3304 def test_sess_cache_no_internal_lookup(self):
3305 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003306 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3307 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3308 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003309 """
3310 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
3311
3312
3313 def test_sess_cache_no_internal_store(self):
3314 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003315 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3316 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3317 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003318 """
3319 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
3320
3321
3322 def test_sess_cache_no_internal(self):
3323 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003324 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3325 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
3326 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003327 """
3328 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
3329
3330
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04003331
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003332class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05003333 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003334 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003335 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003336 def _server(self, sock):
3337 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003338 Create a new server-side SSL :py:obj:`Connection` object wrapped around
3339 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003340 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003341 # Create the server side Connection. This is mostly setup boilerplate
3342 # - use TLSv1, use a particular certificate, etc.
3343 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003344 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
3345 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 -04003346 server_store = server_ctx.get_cert_store()
3347 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3348 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3349 server_ctx.check_privatekey()
3350 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003351 # Here the Connection is actually created. If None is passed as the 2nd
3352 # parameter, it indicates a memory BIO should be created.
3353 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003354 server_conn.set_accept_state()
3355 return server_conn
3356
3357
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003358 def _client(self, sock):
3359 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003360 Create a new client-side SSL :py:obj:`Connection` object wrapped around
3361 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003362 """
3363 # Now create the client side Connection. Similar boilerplate to the
3364 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003365 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003366 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
3367 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 -04003368 client_store = client_ctx.get_cert_store()
3369 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
3370 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
3371 client_ctx.check_privatekey()
3372 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003373 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003374 client_conn.set_connect_state()
3375 return client_conn
3376
3377
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003378 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003379 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003380 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003381 reading from the output of each and writing those bytes to the input of
3382 the other and in this way establish a connection and exchange
3383 application-level bytes with each other.
3384 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003385 server_conn = self._server(None)
3386 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003387
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003388 # There should be no key or nonces yet.
3389 self.assertIdentical(server_conn.master_key(), None)
3390 self.assertIdentical(server_conn.client_random(), None)
3391 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003392
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003393 # First, the handshake needs to happen. We'll deliver bytes back and
3394 # forth between the client and server until neither of them feels like
3395 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003396 self.assertIdentical(
3397 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003398
3399 # Now that the handshake is done, there should be a key and nonces.
3400 self.assertNotIdentical(server_conn.master_key(), None)
3401 self.assertNotIdentical(server_conn.client_random(), None)
3402 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04003403 self.assertEquals(server_conn.client_random(), client_conn.client_random())
3404 self.assertEquals(server_conn.server_random(), client_conn.server_random())
3405 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
3406 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003407
3408 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003409 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05003410
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003411 server_conn.write(important_message)
3412 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003413 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003414 (client_conn, important_message))
3415
3416 client_conn.write(important_message[::-1])
3417 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003418 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003419 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003420
3421
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003422 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003423 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003424 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003425
3426 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09003427 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003428 this test fails, there must be a problem outside the memory BIO
3429 code, as no memory BIO is involved here). Even though this isn't a
3430 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003431 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04003432 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003433
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003434 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05003435 client_conn.send(important_message)
3436 msg = server_conn.recv(1024)
3437 self.assertEqual(msg, important_message)
3438
3439 # Again in the other direction, just for fun.
3440 important_message = important_message[::-1]
3441 server_conn.send(important_message)
3442 msg = client_conn.recv(1024)
3443 self.assertEqual(msg, important_message)
3444
3445
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04003446 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003447 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003448 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
3449 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003450 """
3451 context = Context(SSLv3_METHOD)
3452 client = socket()
3453 clientSSL = Connection(context, client)
Alex Gaynor43307782015-09-04 09:05:45 -04003454 self.assertRaises(TypeError, clientSSL.bio_read, 100)
3455 self.assertRaises(TypeError, clientSSL.bio_write, "foo")
Alex Gaynor7e8b61e2015-09-04 13:13:05 -04003456 self.assertRaises(TypeError, clientSSL.bio_shutdown)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003457
3458
3459 def test_outgoingOverflow(self):
3460 """
3461 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09003462 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003463 returned and that many bytes from the beginning of the input can be
3464 read from the other end of the connection.
3465 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003466 server = self._server(None)
3467 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003468
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003469 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003470
3471 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003472 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003473 # Sanity check. We're trying to test what happens when the entire
3474 # input can't be sent. If the entire input was sent, this test is
3475 # meaningless.
3476 self.assertTrue(sent < size)
3477
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003478 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003479 self.assertIdentical(receiver, server)
3480
3481 # We can rely on all of these bytes being received at once because
3482 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
3483 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003484
3485
3486 def test_shutdown(self):
3487 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003488 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
3489 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003490 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003491 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003492 server.bio_shutdown()
3493 e = self.assertRaises(Error, server.recv, 1024)
3494 # We don't want WantReadError or ZeroReturnError or anything - it's a
3495 # handshake failure.
3496 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003497
3498
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003499 def test_unexpectedEndOfFile(self):
3500 """
3501 If the connection is lost before an orderly SSL shutdown occurs,
3502 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
3503 "Unexpected EOF".
3504 """
3505 server_conn, client_conn = self._loopback()
3506 client_conn.sock_shutdown(SHUT_RDWR)
3507 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
3508 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
3509
3510
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003511 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003512 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003513 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 -04003514
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003515 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003516 before the client and server are connected to each other. This
3517 function should specify a list of CAs for the server to send to the
3518 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09003519 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003520 times.
3521 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003522 server = self._server(None)
3523 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003524 self.assertEqual(client.get_client_ca_list(), [])
3525 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003526 ctx = server.get_context()
3527 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003528 self.assertEqual(client.get_client_ca_list(), [])
3529 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003530 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003531 self.assertEqual(client.get_client_ca_list(), expected)
3532 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003533
3534
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003535 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003536 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003537 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003538 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003539 """
3540 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003541 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
3542 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
3543 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003544
3545
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003546 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003547 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003548 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003549 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09003550 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003551 after the connection is set up.
3552 """
3553 def no_ca(ctx):
3554 ctx.set_client_ca_list([])
3555 return []
3556 self._check_client_ca_list(no_ca)
3557
3558
3559 def test_set_one_ca_list(self):
3560 """
3561 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003562 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003563 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003564 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003565 X509Name after the connection is set up.
3566 """
3567 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3568 cadesc = cacert.get_subject()
3569 def single_ca(ctx):
3570 ctx.set_client_ca_list([cadesc])
3571 return [cadesc]
3572 self._check_client_ca_list(single_ca)
3573
3574
3575 def test_set_multiple_ca_list(self):
3576 """
3577 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003578 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003579 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003580 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003581 X509Names after the connection is set up.
3582 """
3583 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3584 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3585
3586 sedesc = secert.get_subject()
3587 cldesc = clcert.get_subject()
3588
3589 def multiple_ca(ctx):
3590 L = [sedesc, cldesc]
3591 ctx.set_client_ca_list(L)
3592 return L
3593 self._check_client_ca_list(multiple_ca)
3594
3595
3596 def test_reset_ca_list(self):
3597 """
3598 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09003599 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003600 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003601 """
3602 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3603 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3604 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3605
3606 cadesc = cacert.get_subject()
3607 sedesc = secert.get_subject()
3608 cldesc = clcert.get_subject()
3609
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003610 def changed_ca(ctx):
3611 ctx.set_client_ca_list([sedesc, cldesc])
3612 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003613 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003614 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003615
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003616
3617 def test_mutated_ca_list(self):
3618 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003619 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003620 afterwards, this does not affect the list of CA names sent to the
3621 client.
3622 """
3623 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3624 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3625
3626 cadesc = cacert.get_subject()
3627 sedesc = secert.get_subject()
3628
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003629 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003630 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003631 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003632 L.append(sedesc)
3633 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003634 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003635
3636
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003637 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003638 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003639 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003640 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003641 """
3642 ctx = Context(TLSv1_METHOD)
3643 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003644 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003645 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003646 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003647
3648
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003649 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003650 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003651 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09003652 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003653 """
3654 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3655 cadesc = cacert.get_subject()
3656 def single_ca(ctx):
3657 ctx.add_client_ca(cacert)
3658 return [cadesc]
3659 self._check_client_ca_list(single_ca)
3660
3661
3662 def test_multiple_add_client_ca(self):
3663 """
3664 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09003665 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003666 """
3667 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3668 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3669
3670 cadesc = cacert.get_subject()
3671 sedesc = secert.get_subject()
3672
3673 def multiple_ca(ctx):
3674 ctx.add_client_ca(cacert)
3675 ctx.add_client_ca(secert)
3676 return [cadesc, sedesc]
3677 self._check_client_ca_list(multiple_ca)
3678
3679
3680 def test_set_and_add_client_ca(self):
3681 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003682 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
3683 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003684 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003685 """
3686 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3687 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3688 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3689
3690 cadesc = cacert.get_subject()
3691 sedesc = secert.get_subject()
3692 cldesc = clcert.get_subject()
3693
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003694 def mixed_set_add_ca(ctx):
3695 ctx.set_client_ca_list([cadesc, sedesc])
3696 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003697 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003698 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003699
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003700
3701 def test_set_after_add_client_ca(self):
3702 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003703 A call to :py:obj:`Context.set_client_ca_list` after a call to
3704 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003705 call with the names specified by the latter cal.
3706 """
3707 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3708 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3709 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3710
3711 cadesc = cacert.get_subject()
3712 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003713
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003714 def set_replaces_add_ca(ctx):
3715 ctx.add_client_ca(clcert)
3716 ctx.set_client_ca_list([cadesc])
3717 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003718 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003719 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003720
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003721
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003722
3723class ConnectionBIOTests(TestCase):
3724 """
3725 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3726 """
3727 def test_wantReadError(self):
3728 """
3729 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
3730 if there are no bytes available to be read from the BIO.
3731 """
3732 ctx = Context(TLSv1_METHOD)
3733 conn = Connection(ctx, None)
3734 self.assertRaises(WantReadError, conn.bio_read, 1024)
3735
3736
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003737 def test_buffer_size(self):
3738 """
3739 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3740 number of bytes to read and return.
3741 """
3742 ctx = Context(TLSv1_METHOD)
3743 conn = Connection(ctx, None)
3744 conn.set_connect_state()
3745 try:
3746 conn.do_handshake()
3747 except WantReadError:
3748 pass
3749 data = conn.bio_read(2)
3750 self.assertEqual(2, len(data))
3751
3752
3753 if not PY3:
3754 def test_buffer_size_long(self):
3755 """
3756 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3757 :py:obj:`long` as well as :py:obj:`int`.
3758 """
3759 ctx = Context(TLSv1_METHOD)
3760 conn = Connection(ctx, None)
3761 conn.set_connect_state()
3762 try:
3763 conn.do_handshake()
3764 except WantReadError:
3765 pass
3766 data = conn.bio_read(long(2))
3767 self.assertEqual(2, len(data))
3768
3769
3770
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003771
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003772class InfoConstantTests(TestCase):
3773 """
3774 Tests for assorted constants exposed for use in info callbacks.
3775 """
3776 def test_integers(self):
3777 """
3778 All of the info constants are integers.
3779
3780 This is a very weak test. It would be nice to have one that actually
3781 verifies that as certain info events happen, the value passed to the
3782 info callback matches up with the constant exposed by OpenSSL.SSL.
3783 """
3784 for const in [
3785 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3786 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3787 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3788 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3789 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
3790 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
3791
3792 self.assertTrue(isinstance(const, int))
3793
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003794
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003795if __name__ == '__main__':
3796 main()