blob: 5b4523b8706e661bc5953f9bcccf10cf8b9c7e27 [file] [log] [blame]
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05001# Copyright (C) Jean-Paul Calderone
2# See LICENSE for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04003
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04004"""
Jonathan Ballet648875f2011-07-16 14:14:58 +09005Unit tests for :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04006"""
7
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05008from gc import collect, get_referrers
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02009from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE, ESHUTDOWN
Jean-Paul Calderone516c12c2015-04-13 20:34:57 -040010from sys import platform, getfilesystemencoding
Maximilian Hils1d95dea2015-08-17 19:27:20 +020011from socket import MSG_PEEK, SHUT_RDWR, error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040012from os import makedirs
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040013from os.path import join
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -040014from unittest import main
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040015from weakref import ref
Abraham Martinef063482015-03-25 14:06:24 +000016from warnings import catch_warnings, simplefilter
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050017
Hynek Schlawack734d3022015-09-05 19:19:32 +020018import pytest
19
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -040020from six import PY3, text_type, u
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050021
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040022from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080023from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040024from OpenSSL.crypto import dump_privatekey, load_privatekey
25from OpenSSL.crypto import dump_certificate, load_certificate
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040026from OpenSSL.crypto import get_elliptic_curves
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040027
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040028from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
29from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040030from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040031from OpenSSL.SSL import (
32 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
33 TLSv1_1_METHOD, TLSv1_2_METHOD)
34from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040035from OpenSSL.SSL import (
36 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040037
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040038from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050039 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
40 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
41 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
42
43from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070044 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050045from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070046 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040047
Cory Benfieldba1820d2015-04-13 17:39:12 -040048from OpenSSL._util import lib as _lib
49
Jean-Paul Calderone17eca482015-04-13 20:31:07 -040050from OpenSSL.test.util import WARNING_TYPE_EXPECTED, NON_ASCII, TestCase, b
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040051from OpenSSL.test.test_crypto import (
Jean-Paul Calderoneda6399a2015-04-13 20:52:29 -040052 cleartextCertificatePEM, cleartextPrivateKeyPEM,
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040053 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
54 root_cert_pem)
55
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050056try:
57 from OpenSSL.SSL import OP_NO_QUERY_MTU
58except ImportError:
59 OP_NO_QUERY_MTU = None
60try:
61 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
62except ImportError:
63 OP_COOKIE_EXCHANGE = None
64try:
65 from OpenSSL.SSL import OP_NO_TICKET
66except ImportError:
67 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040068
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040069try:
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -040070 from OpenSSL.SSL import OP_NO_COMPRESSION
71except ImportError:
72 OP_NO_COMPRESSION = None
73
74try:
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040075 from OpenSSL.SSL import MODE_RELEASE_BUFFERS
76except ImportError:
77 MODE_RELEASE_BUFFERS = None
78
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040079try:
80 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
81except ImportError:
82 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
83
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040084from OpenSSL.SSL import (
85 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
86 SSL_ST_OK, SSL_ST_RENEGOTIATE,
87 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
88 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
89 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
90 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040091
Hynek Schlawackde00dd52015-09-05 19:09:26 +020092
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040093# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
94# to use)
95dhparam = """\
96-----BEGIN DH PARAMETERS-----
97MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
98-----END DH PARAMETERS-----
99"""
100
101
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400102def join_bytes_or_unicode(prefix, suffix):
103 """
104 Join two path components of either ``bytes`` or ``unicode``.
105
106 The return type is the same as the type of ``prefix``.
107 """
108 # If the types are the same, nothing special is necessary.
109 if type(prefix) == type(suffix):
110 return join(prefix, suffix)
111
112 # Otherwise, coerce suffix to the type of prefix.
113 if isinstance(prefix, text_type):
114 return join(prefix, suffix.decode(getfilesystemencoding()))
115 else:
116 return join(prefix, suffix.encode(getfilesystemencoding()))
117
118
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400119def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400120 return ok
121
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400122
Rick Deanb1ccd562009-07-09 23:52:39 -0500123def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400124 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400125 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400126 """
127 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500128 port = socket()
129 port.bind(('', 0))
130 port.listen(1)
131 client = socket()
132 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400133 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400134 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500135 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500136
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400137 # Let's pass some unencrypted data to make sure our socket connection is
138 # fine. Just one byte, so we don't have to worry about buffers getting
139 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400140 server.send(b("x"))
141 assert client.recv(1024) == b("x")
142 client.send(b("y"))
143 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500144
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400145 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400146 server.setblocking(False)
147 client.setblocking(False)
Jim Shaver46f28912015-05-29 19:32:16 -0400148
Rick Deanb1ccd562009-07-09 23:52:39 -0500149 return (server, client)
150
151
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400152def handshake(client, server):
153 conns = [client, server]
154 while conns:
155 for conn in conns:
156 try:
157 conn.do_handshake()
158 except WantReadError:
159 pass
160 else:
161 conns.remove(conn)
162
163
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400164def _create_certificate_chain():
165 """
166 Construct and return a chain of certificates.
167
168 1. A new self-signed certificate authority certificate (cacert)
169 2. A new intermediate certificate signed by cacert (icert)
170 3. A new server certificate signed by icert (scert)
171 """
172 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
173
174 # Step 1
175 cakey = PKey()
176 cakey.generate_key(TYPE_RSA, 512)
177 cacert = X509()
178 cacert.get_subject().commonName = "Authority Certificate"
179 cacert.set_issuer(cacert.get_subject())
180 cacert.set_pubkey(cakey)
181 cacert.set_notBefore(b("20000101000000Z"))
182 cacert.set_notAfter(b("20200101000000Z"))
183 cacert.add_extensions([caext])
184 cacert.set_serial_number(0)
185 cacert.sign(cakey, "sha1")
186
187 # Step 2
188 ikey = PKey()
189 ikey.generate_key(TYPE_RSA, 512)
190 icert = X509()
191 icert.get_subject().commonName = "Intermediate Certificate"
192 icert.set_issuer(cacert.get_subject())
193 icert.set_pubkey(ikey)
194 icert.set_notBefore(b("20000101000000Z"))
195 icert.set_notAfter(b("20200101000000Z"))
196 icert.add_extensions([caext])
197 icert.set_serial_number(0)
198 icert.sign(cakey, "sha1")
199
200 # Step 3
201 skey = PKey()
202 skey.generate_key(TYPE_RSA, 512)
203 scert = X509()
204 scert.get_subject().commonName = "Server Certificate"
205 scert.set_issuer(icert.get_subject())
206 scert.set_pubkey(skey)
207 scert.set_notBefore(b("20000101000000Z"))
208 scert.set_notAfter(b("20200101000000Z"))
209 scert.add_extensions([
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200210 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400211 scert.set_serial_number(0)
212 scert.sign(ikey, "sha1")
213
214 return [(cakey, cacert), (ikey, icert), (skey, scert)]
215
216
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400217class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400218 """
219 Helper mixin which defines methods for creating a connected socket pair and
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200220 for forcing two connected SSL sockets to talk to each other via memory
221 BIOs.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400222 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500223 def _loopbackClientFactory(self, socket):
224 client = Connection(Context(TLSv1_METHOD), socket)
225 client.set_connect_state()
226 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400227
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500228 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400229 ctx = Context(TLSv1_METHOD)
230 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
231 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500232 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400233 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500234 return server
235
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500236 def _loopback(self, serverFactory=None, clientFactory=None):
237 if serverFactory is None:
238 serverFactory = self._loopbackServerFactory
239 if clientFactory is None:
240 clientFactory = self._loopbackClientFactory
241
242 (server, client) = socket_pair()
243 server = serverFactory(server)
244 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400245
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400246 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400247
248 server.setblocking(True)
249 client.setblocking(True)
250 return server, client
251
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400252 def _interactInMemory(self, client_conn, server_conn):
253 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900254 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400255 objects. Copy bytes back and forth between their send/receive buffers
256 for as long as there is anything to copy. When there is nothing more
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200257 to copy, return :py:obj:`None`. If one of them actually manages to
258 deliver some application bytes, return a two-tuple of the connection
259 from which the bytes were read and the bytes themselves.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400260 """
261 wrote = True
262 while wrote:
263 # Loop until neither side has anything to say
264 wrote = False
265
266 # Copy stuff from each side's send buffer to the other side's
267 # receive buffer.
268 for (read, write) in [(client_conn, server_conn),
269 (server_conn, client_conn)]:
270
271 # Give the side a chance to generate some more bytes, or
272 # succeed.
273 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400274 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400275 except WantReadError:
276 # It didn't succeed, so we'll hope it generated some
277 # output.
278 pass
279 else:
280 # It did succeed, so we'll stop now and let the caller deal
281 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400282 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400283
284 while True:
285 # Keep copying as long as there's more stuff there.
286 try:
287 dirty = read.bio_read(4096)
288 except WantReadError:
289 # Okay, nothing more waiting to be sent. Stop
290 # processing this send buffer.
291 break
292 else:
293 # Keep track of the fact that someone generated some
294 # output.
295 wrote = True
296 write.bio_write(dirty)
297
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400298 def _handshakeInMemory(self, client_conn, server_conn):
Jean-Paul Calderoneb2b40782014-05-06 08:47:40 -0400299 """
300 Perform the TLS handshake between two :py:class:`Connection` instances
301 connected to each other via memory BIOs.
302 """
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400303 client_conn.set_connect_state()
304 server_conn.set_accept_state()
305
306 for conn in [client_conn, server_conn]:
307 try:
308 conn.do_handshake()
309 except WantReadError:
310 pass
311
312 self._interactInMemory(client_conn, server_conn)
313
314
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400315class VersionTests(TestCase):
316 """
317 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900318 :py:obj:`OpenSSL.SSL.SSLeay_version` and
319 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400320 """
321 def test_OPENSSL_VERSION_NUMBER(self):
322 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900323 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400324 byte and the patch, fix, minor, and major versions in the
325 nibbles above that.
326 """
327 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
328
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400329 def test_SSLeay_version(self):
330 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900331 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400332 one of a number of version strings based on that indicator.
333 """
334 versions = {}
335 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
336 SSLEAY_PLATFORM, SSLEAY_DIR]:
337 version = SSLeay_version(t)
338 versions[version] = t
339 self.assertTrue(isinstance(version, bytes))
340 self.assertEqual(len(versions), 5)
341
342
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400343class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400344 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900345 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400346 """
347 def test_method(self):
348 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200349 :py:obj:`Context` can be instantiated with one of
350 :py:obj:`SSLv2_METHOD`, :py:obj:`SSLv3_METHOD`,
351 :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400352 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400353 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400354 methods = [
355 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
356 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400357 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400358
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400359 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
360 for meth in maybe:
361 try:
362 Context(meth)
363 except (Error, ValueError):
364 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
365 # don't. Difficult to say in advance.
366 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400367
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400368 self.assertRaises(TypeError, Context, "")
369 self.assertRaises(ValueError, Context, 10)
370
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500371 if not PY3:
372 def test_method_long(self):
373 """
374 On Python 2 :py:class:`Context` accepts values of type
375 :py:obj:`long` as well as :py:obj:`int`.
376 """
377 Context(long(TLSv1_METHOD))
378
Rick Deane15b1472009-07-09 15:53:42 -0500379 def test_type(self):
380 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200381 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type
382 object and can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500383 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400384 self.assertIdentical(Context, ContextType)
385 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500386
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400387 def test_use_privatekey(self):
388 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200389 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey`
390 instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400391 """
392 key = PKey()
393 key.generate_key(TYPE_RSA, 128)
394 ctx = Context(TLSv1_METHOD)
395 ctx.use_privatekey(key)
396 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400397
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800398 def test_use_privatekey_file_missing(self):
399 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200400 :py:obj:`Context.use_privatekey_file` raises
401 :py:obj:`OpenSSL.SSL.Error` when passed the name of a file which does
402 not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800403 """
404 ctx = Context(TLSv1_METHOD)
405 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
406
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400407 def _use_privatekey_file_test(self, pemfile, filetype):
408 """
409 Verify that calling ``Context.use_privatekey_file`` with the given
410 arguments does not raise an exception.
411 """
412 key = PKey()
413 key.generate_key(TYPE_RSA, 128)
414
415 with open(pemfile, "wt") as pem:
416 pem.write(
417 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
418 )
419
420 ctx = Context(TLSv1_METHOD)
421 ctx.use_privatekey_file(pemfile, filetype)
422
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400423 def test_use_privatekey_file_bytes(self):
424 """
425 A private key can be specified from a file by passing a ``bytes``
426 instance giving the file name to ``Context.use_privatekey_file``.
427 """
428 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400429 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400430 FILETYPE_PEM,
431 )
432
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400433 def test_use_privatekey_file_unicode(self):
434 """
435 A private key can be specified from a file by passing a ``unicode``
436 instance giving the file name to ``Context.use_privatekey_file``.
437 """
438 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400439 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400440 FILETYPE_PEM,
441 )
442
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500443 if not PY3:
444 def test_use_privatekey_file_long(self):
445 """
446 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
447 filetype of type :py:obj:`long` as well as :py:obj:`int`.
448 """
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400449 self._use_privatekey_file_test(self.mktemp(), long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500450
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800451 def test_use_certificate_wrong_args(self):
452 """
453 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200454 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as
455 an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800456 """
457 ctx = Context(TLSv1_METHOD)
458 self.assertRaises(TypeError, ctx.use_certificate)
459 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200460 self.assertRaises(
461 TypeError, ctx.use_certificate, X509(), "hello, world"
462 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800463
464 def test_use_certificate_uninitialized(self):
465 """
466 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
467 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
468 initialized (ie, which does not actually have any certificate data).
469 """
470 ctx = Context(TLSv1_METHOD)
471 self.assertRaises(Error, ctx.use_certificate, X509())
472
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800473 def test_use_certificate(self):
474 """
475 :py:obj:`Context.use_certificate` sets the certificate which will be
476 used to identify connections created using the context.
477 """
478 # TODO
479 # Hard to assert anything. But we could set a privatekey then ask
480 # OpenSSL if the cert and key agree using check_privatekey. Then as
481 # long as check_privatekey works right we're good...
482 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200483 ctx.use_certificate(
484 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
485 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800486
487 def test_use_certificate_file_wrong_args(self):
488 """
489 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
490 called with zero arguments or more than two arguments, or if the first
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200491 argument is not a byte string or the second argumnent is not an
492 integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800493 """
494 ctx = Context(TLSv1_METHOD)
495 self.assertRaises(TypeError, ctx.use_certificate_file)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200496 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile",
497 object())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800498 self.assertRaises(
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200499 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM,
500 object())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800501 self.assertRaises(
502 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
503 self.assertRaises(
504 TypeError, ctx.use_certificate_file, b"somefile", object())
505
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800506 def test_use_certificate_file_missing(self):
507 """
508 :py:obj:`Context.use_certificate_file` raises
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200509 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does
510 not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800511 """
512 ctx = Context(TLSv1_METHOD)
513 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
514
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400515 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800516 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400517 Verify that calling ``Context.use_certificate_file`` with the given
518 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800519 """
520 # TODO
521 # Hard to assert anything. But we could set a privatekey then ask
522 # OpenSSL if the cert and key agree using check_privatekey. Then as
523 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400524 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800525 pem_file.write(cleartextCertificatePEM)
526
527 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400528 ctx.use_certificate_file(certificate_file)
529
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400530 def test_use_certificate_file_bytes(self):
531 """
532 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
533 ``bytes`` filename) which will be used to identify connections created
534 using the context.
535 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400536 filename = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400537 self._use_certificate_file_test(filename)
538
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400539 def test_use_certificate_file_unicode(self):
540 """
541 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
542 ``bytes`` filename) which will be used to identify connections created
543 using the context.
544 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400545 filename = self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400546 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800547
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500548 if not PY3:
549 def test_use_certificate_file_long(self):
550 """
551 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
552 filetype of type :py:obj:`long` as well as :py:obj:`int`.
553 """
554 pem_filename = self.mktemp()
555 with open(pem_filename, "wb") as pem_file:
556 pem_file.write(cleartextCertificatePEM)
557
558 ctx = Context(TLSv1_METHOD)
559 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
560
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500561 def test_check_privatekey_valid(self):
562 """
563 :py:obj:`Context.check_privatekey` returns :py:obj:`None` if the
564 :py:obj:`Context` instance has been configured to use a matched key and
565 certificate pair.
566 """
567 key = load_privatekey(FILETYPE_PEM, client_key_pem)
568 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
569 context = Context(TLSv1_METHOD)
570 context.use_privatekey(key)
571 context.use_certificate(cert)
572 self.assertIs(None, context.check_privatekey())
573
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500574 def test_check_privatekey_invalid(self):
575 """
576 :py:obj:`Context.check_privatekey` raises :py:obj:`Error` if the
577 :py:obj:`Context` instance has been configured to use a key and
578 certificate pair which don't relate to each other.
579 """
580 key = load_privatekey(FILETYPE_PEM, client_key_pem)
581 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
582 context = Context(TLSv1_METHOD)
583 context.use_privatekey(key)
584 context.use_certificate(cert)
585 self.assertRaises(Error, context.check_privatekey)
586
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500587 def test_check_privatekey_wrong_args(self):
588 """
589 :py:obj:`Context.check_privatekey` raises :py:obj:`TypeError` if called
590 with other than no arguments.
591 """
592 context = Context(TLSv1_METHOD)
593 self.assertRaises(TypeError, context.check_privatekey, object())
594
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400595 def test_set_app_data_wrong_args(self):
596 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200597 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called
598 with other than one argument.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400599 """
600 context = Context(TLSv1_METHOD)
601 self.assertRaises(TypeError, context.set_app_data)
602 self.assertRaises(TypeError, context.set_app_data, None, None)
603
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400604 def test_get_app_data_wrong_args(self):
605 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200606 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called
607 with any arguments.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400608 """
609 context = Context(TLSv1_METHOD)
610 self.assertRaises(TypeError, context.get_app_data, None)
611
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400612 def test_app_data(self):
613 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200614 :py:obj:`Context.set_app_data` stores an object for later retrieval
615 using :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400616 """
617 app_data = object()
618 context = Context(TLSv1_METHOD)
619 context.set_app_data(app_data)
620 self.assertIdentical(context.get_app_data(), app_data)
621
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400622 def test_set_options_wrong_args(self):
623 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200624 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with
625 the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400626 """
627 context = Context(TLSv1_METHOD)
628 self.assertRaises(TypeError, context.set_options)
629 self.assertRaises(TypeError, context.set_options, None)
630 self.assertRaises(TypeError, context.set_options, 1, None)
631
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500632 def test_set_options(self):
633 """
634 :py:obj:`Context.set_options` returns the new options value.
635 """
636 context = Context(TLSv1_METHOD)
637 options = context.set_options(OP_NO_SSLv2)
638 self.assertTrue(OP_NO_SSLv2 & options)
639
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500640 if not PY3:
641 def test_set_options_long(self):
642 """
643 On Python 2 :py:obj:`Context.set_options` accepts values of type
644 :py:obj:`long` as well as :py:obj:`int`.
645 """
646 context = Context(TLSv1_METHOD)
647 options = context.set_options(long(OP_NO_SSLv2))
648 self.assertTrue(OP_NO_SSLv2 & options)
649
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300650 def test_set_mode_wrong_args(self):
651 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200652 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with
653 the wrong number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300654 """
655 context = Context(TLSv1_METHOD)
656 self.assertRaises(TypeError, context.set_mode)
657 self.assertRaises(TypeError, context.set_mode, None)
658 self.assertRaises(TypeError, context.set_mode, 1, None)
659
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400660 if MODE_RELEASE_BUFFERS is not None:
661 def test_set_mode(self):
662 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200663 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the
664 newly set mode.
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400665 """
666 context = Context(TLSv1_METHOD)
667 self.assertTrue(
668 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500669
670 if not PY3:
671 def test_set_mode_long(self):
672 """
673 On Python 2 :py:obj:`Context.set_mode` accepts values of type
674 :py:obj:`long` as well as :py:obj:`int`.
675 """
676 context = Context(TLSv1_METHOD)
677 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
678 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400679 else:
680 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
681
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400682 def test_set_timeout_wrong_args(self):
683 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200684 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with
685 the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400686 """
687 context = Context(TLSv1_METHOD)
688 self.assertRaises(TypeError, context.set_timeout)
689 self.assertRaises(TypeError, context.set_timeout, None)
690 self.assertRaises(TypeError, context.set_timeout, 1, None)
691
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400692 def test_get_timeout_wrong_args(self):
693 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200694 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with
695 any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400696 """
697 context = Context(TLSv1_METHOD)
698 self.assertRaises(TypeError, context.get_timeout, None)
699
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400700 def test_timeout(self):
701 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200702 :py:obj:`Context.set_timeout` sets the session timeout for all
703 connections created using the context object.
704 :py:obj:`Context.get_timeout` retrieves this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400705 """
706 context = Context(TLSv1_METHOD)
707 context.set_timeout(1234)
708 self.assertEquals(context.get_timeout(), 1234)
709
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500710 if not PY3:
711 def test_timeout_long(self):
712 """
713 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
714 `long` as well as int.
715 """
716 context = Context(TLSv1_METHOD)
717 context.set_timeout(long(1234))
718 self.assertEquals(context.get_timeout(), 1234)
719
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400720 def test_set_verify_depth_wrong_args(self):
721 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200722 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called
723 with the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400724 """
725 context = Context(TLSv1_METHOD)
726 self.assertRaises(TypeError, context.set_verify_depth)
727 self.assertRaises(TypeError, context.set_verify_depth, None)
728 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
729
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400730 def test_get_verify_depth_wrong_args(self):
731 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200732 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called
733 with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400734 """
735 context = Context(TLSv1_METHOD)
736 self.assertRaises(TypeError, context.get_verify_depth, None)
737
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400738 def test_verify_depth(self):
739 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200740 :py:obj:`Context.set_verify_depth` sets the number of certificates in
741 a chain to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900742 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400743 """
744 context = Context(TLSv1_METHOD)
745 context.set_verify_depth(11)
746 self.assertEquals(context.get_verify_depth(), 11)
747
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500748 if not PY3:
749 def test_verify_depth_long(self):
750 """
751 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
752 type `long` as well as int.
753 """
754 context = Context(TLSv1_METHOD)
755 context.set_verify_depth(long(11))
756 self.assertEquals(context.get_verify_depth(), 11)
757
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400758 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400759 """
760 Write a new private key out to a new file, encrypted using the given
761 passphrase. Return the path to the new file.
762 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400763 key = PKey()
764 key.generate_key(TYPE_RSA, 128)
765 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400766 fObj = open(pemFile, 'w')
767 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
768 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400769 fObj.close()
770 return pemFile
771
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400772 def test_set_passwd_cb_wrong_args(self):
773 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200774 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called
775 with the wrong arguments or with a non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400776 """
777 context = Context(TLSv1_METHOD)
778 self.assertRaises(TypeError, context.set_passwd_cb)
779 self.assertRaises(TypeError, context.set_passwd_cb, None)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200780 self.assertRaises(
781 TypeError, context.set_passwd_cb, lambda: None, None, None
Hynek Schlawack2c013a92015-09-05 19:33:05 +0200782 ) # pragma: nocover
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400783
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400784 def test_set_passwd_cb(self):
785 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200786 :py:obj:`Context.set_passwd_cb` accepts a callable which will be
787 invoked when a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400788 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400789 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400790 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400791 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200792
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400793 def passphraseCallback(maxlen, verify, extra):
794 calledWith.append((maxlen, verify, extra))
795 return passphrase
796 context = Context(TLSv1_METHOD)
797 context.set_passwd_cb(passphraseCallback)
798 context.use_privatekey_file(pemFile)
799 self.assertTrue(len(calledWith), 1)
800 self.assertTrue(isinstance(calledWith[0][0], int))
801 self.assertTrue(isinstance(calledWith[0][1], int))
802 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400803
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400804 def test_passwd_callback_exception(self):
805 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200806 :py:obj:`Context.use_privatekey_file` propagates any exception raised
807 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400808 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400809 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200810
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400811 def passphraseCallback(maxlen, verify, extra):
812 raise RuntimeError("Sorry, I am a fail.")
813
814 context = Context(TLSv1_METHOD)
815 context.set_passwd_cb(passphraseCallback)
816 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
817
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400818 def test_passwd_callback_false(self):
819 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200820 :py:obj:`Context.use_privatekey_file` raises
821 :py:obj:`OpenSSL.SSL.Error` if the passphrase callback returns a false
822 value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400823 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400824 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200825
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400826 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500827 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400828
829 context = Context(TLSv1_METHOD)
830 context.set_passwd_cb(passphraseCallback)
831 self.assertRaises(Error, context.use_privatekey_file, pemFile)
832
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400833 def test_passwd_callback_non_string(self):
834 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200835 :py:obj:`Context.use_privatekey_file` raises
836 :py:obj:`OpenSSL.SSL.Error` if the passphrase callback returns a true
837 non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400838 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400839 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200840
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400841 def passphraseCallback(maxlen, verify, extra):
842 return 10
843
844 context = Context(TLSv1_METHOD)
845 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800846 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400847
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400848 def test_passwd_callback_too_long(self):
849 """
850 If the passphrase returned by the passphrase callback returns a string
851 longer than the indicated maximum length, it is truncated.
852 """
853 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400854 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400855 pemFile = self._write_encrypted_pem(passphrase)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200856
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400857 def passphraseCallback(maxlen, verify, extra):
858 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400859 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400860
861 context = Context(TLSv1_METHOD)
862 context.set_passwd_cb(passphraseCallback)
863 # This shall succeed because the truncated result is the correct
864 # passphrase.
865 context.use_privatekey_file(pemFile)
866
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400867 def test_set_info_callback(self):
868 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200869 :py:obj:`Context.set_info_callback` accepts a callable which will be
870 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400871 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500872 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400873
874 clientSSL = Connection(Context(TLSv1_METHOD), client)
875 clientSSL.set_connect_state()
876
877 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200878
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400879 def info(conn, where, ret):
880 called.append((conn, where, ret))
881 context = Context(TLSv1_METHOD)
882 context.set_info_callback(info)
883 context.use_certificate(
884 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
885 context.use_privatekey(
886 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
887
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400888 serverSSL = Connection(context, server)
889 serverSSL.set_accept_state()
890
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500891 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400892
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500893 # The callback must always be called with a Connection instance as the
894 # first argument. It would probably be better to split this into
895 # separate tests for client and server side info callbacks so we could
896 # assert it is called with the right Connection instance. It would
897 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500898 notConnections = [
899 conn for (conn, where, ret) in called
900 if not isinstance(conn, Connection)]
901 self.assertEqual(
902 [], notConnections,
903 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400904
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400905 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400906 """
907 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400908 its :py:obj:`load_verify_locations` method with the given arguments.
909 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400910 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500911 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400912
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400913 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400914 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400915 # Require that the server certificate verify properly or the
916 # connection will fail.
917 clientContext.set_verify(
918 VERIFY_PEER,
919 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
920
921 clientSSL = Connection(clientContext, client)
922 clientSSL.set_connect_state()
923
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400924 serverContext = Context(TLSv1_METHOD)
925 serverContext.use_certificate(
926 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
927 serverContext.use_privatekey(
928 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
929
930 serverSSL = Connection(serverContext, server)
931 serverSSL.set_accept_state()
932
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400933 # Without load_verify_locations above, the handshake
934 # will fail:
935 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
936 # 'certificate verify failed')]
937 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400938
939 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400940 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400941
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400942 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400943 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400944 Verify that if path to a file containing a certificate is passed to
945 ``Context.load_verify_locations`` for the ``cafile`` parameter, that
946 certificate is used as a trust root for the purposes of verifying
947 connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400948 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400949 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400950 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400951 fObj.close()
952
953 self._load_verify_locations_test(cafile)
954
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400955 def test_load_verify_bytes_cafile(self):
956 """
957 :py:obj:`Context.load_verify_locations` accepts a file name as a
958 ``bytes`` instance and uses the certificates within for verification
959 purposes.
960 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400961 cafile = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400962 self._load_verify_cafile(cafile)
963
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400964 def test_load_verify_unicode_cafile(self):
965 """
966 :py:obj:`Context.load_verify_locations` accepts a file name as a
967 ``unicode`` instance and uses the certificates within for verification
968 purposes.
969 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -0400970 self._load_verify_cafile(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400971 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -0400972 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400973
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400974 def test_load_verify_invalid_file(self):
975 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200976 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when
977 passed a non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400978 """
979 clientContext = Context(TLSv1_METHOD)
980 self.assertRaises(
981 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400982
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400983 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400984 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400985 Verify that if path to a directory containing certificate files is
986 passed to ``Context.load_verify_locations`` for the ``capath``
987 parameter, those certificates are used as trust roots for the purposes
988 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400989 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400990 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400991 # Hash values computed manually with c_rehash to avoid depending on
992 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
993 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500994 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400995 cafile = join_bytes_or_unicode(capath, name)
996 with open(cafile, 'w') as fObj:
997 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400998
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400999 self._load_verify_locations_test(None, capath)
1000
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001001 def test_load_verify_directory_bytes_capath(self):
1002 """
1003 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1004 ``bytes`` instance and uses the certificates within for verification
1005 purposes.
1006 """
1007 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001008 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001009 )
1010
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001011 def test_load_verify_directory_unicode_capath(self):
1012 """
1013 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1014 ``unicode`` instance and uses the certificates within for verification
1015 purposes.
1016 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001017 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001018 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001019 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001020
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001021 def test_load_verify_locations_wrong_args(self):
1022 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001023 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if
1024 called with the wrong number of arguments or with non-:py:obj:`str`
1025 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001026 """
1027 context = Context(TLSv1_METHOD)
1028 self.assertRaises(TypeError, context.load_verify_locations)
1029 self.assertRaises(TypeError, context.load_verify_locations, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001030 self.assertRaises(
1031 TypeError, context.load_verify_locations, object(), object()
1032 )
1033 self.assertRaises(
1034 TypeError, context.load_verify_locations, None, None, None
1035 )
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001036
Hynek Schlawack734d3022015-09-05 19:19:32 +02001037 @pytest.mark.skipif(
1038 platform == "win32",
1039 reason="set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001040 "See LP#404343 and LP#404344."
Hynek Schlawack734d3022015-09-05 19:19:32 +02001041 )
1042 def test_set_default_verify_paths(self):
1043 """
1044 :py:obj:`Context.set_default_verify_paths` causes the
1045 platform-specific CA certificate locations to be used for
1046 verification purposes.
1047 """
1048 # Testing this requires a server with a certificate signed by one
1049 # of the CAs in the platform CA location. Getting one of those
1050 # costs money. Fortunately (or unfortunately, depending on your
1051 # perspective), it's easy to think of a public server on the
1052 # internet which has such a certificate. Connecting to the network
1053 # in a unit test is bad, but it's the only way I can think of to
1054 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001055
Hynek Schlawack734d3022015-09-05 19:19:32 +02001056 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
1057 context = Context(TLSv1_METHOD)
1058 context.set_default_verify_paths()
1059 context.set_verify(
1060 VERIFY_PEER,
1061 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001062
Hynek Schlawack734d3022015-09-05 19:19:32 +02001063 client = socket()
1064 client.connect(('verisign.com', 443))
1065 clientSSL = Connection(context, client)
1066 clientSSL.set_connect_state()
1067 clientSSL.do_handshake()
1068 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
1069 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001070
1071 def test_set_default_verify_paths_signature(self):
1072 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001073 :py:obj:`Context.set_default_verify_paths` takes no arguments and
1074 raises :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001075 """
1076 context = Context(TLSv1_METHOD)
1077 self.assertRaises(TypeError, context.set_default_verify_paths, None)
1078 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
1079 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001080
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001081 def test_add_extra_chain_cert_invalid_cert(self):
1082 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001083 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if
1084 called with other than one argument or if called with an object which
1085 is not an instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001086 """
1087 context = Context(TLSv1_METHOD)
1088 self.assertRaises(TypeError, context.add_extra_chain_cert)
1089 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001090 self.assertRaises(
1091 TypeError, context.add_extra_chain_cert, object(), object()
1092 )
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001093
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001094 def _handshake_test(self, serverContext, clientContext):
1095 """
1096 Verify that a client and server created with the given contexts can
1097 successfully handshake and communicate.
1098 """
1099 serverSocket, clientSocket = socket_pair()
1100
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001101 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001102 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001103
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001104 client = Connection(clientContext, clientSocket)
1105 client.set_connect_state()
1106
1107 # Make them talk to each other.
1108 # self._interactInMemory(client, server)
1109 for i in range(3):
1110 for s in [client, server]:
1111 try:
1112 s.do_handshake()
1113 except WantReadError:
1114 pass
1115
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001116 def test_set_verify_callback_connection_argument(self):
1117 """
1118 The first argument passed to the verify callback is the
1119 :py:class:`Connection` instance for which verification is taking place.
1120 """
1121 serverContext = Context(TLSv1_METHOD)
1122 serverContext.use_privatekey(
1123 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1124 serverContext.use_certificate(
1125 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1126 serverConnection = Connection(serverContext, None)
1127
1128 class VerifyCallback(object):
1129 def callback(self, connection, *args):
1130 self.connection = connection
1131 return 1
1132
1133 verify = VerifyCallback()
1134 clientContext = Context(TLSv1_METHOD)
1135 clientContext.set_verify(VERIFY_PEER, verify.callback)
1136 clientConnection = Connection(clientContext, None)
1137 clientConnection.set_connect_state()
1138
1139 self._handshakeInMemory(clientConnection, serverConnection)
1140
1141 self.assertIdentical(verify.connection, clientConnection)
1142
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001143 def test_set_verify_callback_exception(self):
1144 """
1145 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1146 exception, verification fails and the exception is propagated to the
1147 caller of :py:obj:`Connection.do_handshake`.
1148 """
1149 serverContext = Context(TLSv1_METHOD)
1150 serverContext.use_privatekey(
1151 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1152 serverContext.use_certificate(
1153 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1154
1155 clientContext = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001156
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001157 def verify_callback(*args):
1158 raise Exception("silly verify failure")
1159 clientContext.set_verify(VERIFY_PEER, verify_callback)
1160
1161 exc = self.assertRaises(
1162 Exception, self._handshake_test, serverContext, clientContext)
1163 self.assertEqual("silly verify failure", str(exc))
1164
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001165 def test_add_extra_chain_cert(self):
1166 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001167 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509`
1168 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001169
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001170 See :py:obj:`_create_certificate_chain` for the details of the
1171 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001172
1173 The chain is tested by starting a server with scert and connecting
1174 to it with a client which trusts cacert and requires verification to
1175 succeed.
1176 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001177 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001178 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1179
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001180 # Dump the CA certificate to a file because that's the only way to load
1181 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001182 for cert, name in [(cacert, 'ca.pem'),
1183 (icert, 'i.pem'),
1184 (scert, 's.pem')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001185 with open(join(self.tmpdir, name), 'w') as f:
1186 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001187
Hynek Schlawack1902c012015-04-16 15:06:41 -04001188 for key, name in [(cakey, 'ca.key'),
1189 (ikey, 'i.key'),
1190 (skey, 's.key')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001191 with open(join(self.tmpdir, name), 'w') as f:
1192 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001193
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001194 # Create the server context
1195 serverContext = Context(TLSv1_METHOD)
1196 serverContext.use_privatekey(skey)
1197 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001198 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001199 serverContext.add_extra_chain_cert(icert)
1200
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001201 # Create the client
1202 clientContext = Context(TLSv1_METHOD)
1203 clientContext.set_verify(
1204 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001205 clientContext.load_verify_locations(join(self.tmpdir, "ca.pem"))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001206
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001207 # Try it out.
1208 self._handshake_test(serverContext, clientContext)
1209
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001210 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001211 """
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001212 Verify that :py:obj:`Context.use_certificate_chain_file` reads a
1213 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001214
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001215 The chain is tested by starting a server with scert and connecting to
1216 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001217 succeed.
1218 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001219 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001220 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1221
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001222 makedirs(certdir)
1223
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001224 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1225 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001226
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001227 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001228 with open(chainFile, 'wb') as fObj:
1229 # Most specific to least general.
1230 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1231 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1232 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1233
1234 with open(caFile, 'w') as fObj:
1235 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001236
1237 serverContext = Context(TLSv1_METHOD)
1238 serverContext.use_certificate_chain_file(chainFile)
1239 serverContext.use_privatekey(skey)
1240
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001241 clientContext = Context(TLSv1_METHOD)
1242 clientContext.set_verify(
1243 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001244 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001245
1246 self._handshake_test(serverContext, clientContext)
1247
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001248 def test_use_certificate_chain_file_bytes(self):
1249 """
1250 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1251 an instance of ``bytes``) to specify additional certificates to use to
1252 construct and verify a trust chain.
1253 """
1254 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001255 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001256 )
1257
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001258 def test_use_certificate_chain_file_unicode(self):
1259 """
1260 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1261 an instance of ``unicode``) to specify additional certificates to use
1262 to construct and verify a trust chain.
1263 """
1264 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001265 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001266 )
1267
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001268 def test_use_certificate_chain_file_wrong_args(self):
1269 """
1270 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1271 if passed zero or more than one argument or when passed a non-byte
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001272 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error`
1273 when passed a bad chain file name (for example, the name of a file
1274 which does not exist).
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001275 """
1276 context = Context(TLSv1_METHOD)
1277 self.assertRaises(TypeError, context.use_certificate_chain_file)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001278 self.assertRaises(
1279 TypeError, context.use_certificate_chain_file, object()
1280 )
1281 self.assertRaises(
1282 TypeError, context.use_certificate_chain_file, b"foo", object()
1283 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001284
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001285 self.assertRaises(
1286 Error, context.use_certificate_chain_file, self.mktemp()
1287 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001288
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001289 # XXX load_client_ca
1290 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001291
1292 def test_get_verify_mode_wrong_args(self):
1293 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001294 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called
1295 with any arguments.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001296 """
1297 context = Context(TLSv1_METHOD)
1298 self.assertRaises(TypeError, context.get_verify_mode, None)
1299
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001300 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001301 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001302 :py:obj:`Context.get_verify_mode` returns the verify mode flags
1303 previously passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001304 """
1305 context = Context(TLSv1_METHOD)
1306 self.assertEquals(context.get_verify_mode(), 0)
1307 context.set_verify(
1308 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1309 self.assertEquals(
1310 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1311
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001312 if not PY3:
1313 def test_set_verify_mode_long(self):
1314 """
1315 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1316 type :py:obj:`long` as well as :py:obj:`int`.
1317 """
1318 context = Context(TLSv1_METHOD)
1319 self.assertEquals(context.get_verify_mode(), 0)
1320 context.set_verify(
1321 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None)
1322 self.assertEquals(
1323 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1324
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001325 def test_load_tmp_dh_wrong_args(self):
1326 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001327 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with
1328 the wrong number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001329 """
1330 context = Context(TLSv1_METHOD)
1331 self.assertRaises(TypeError, context.load_tmp_dh)
1332 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1333 self.assertRaises(TypeError, context.load_tmp_dh, object())
1334
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001335 def test_load_tmp_dh_missing_file(self):
1336 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001337 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the
1338 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001339 """
1340 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001341 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001342
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001343 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001344 """
1345 Verify that calling ``Context.load_tmp_dh`` with the given filename
1346 does not raise an exception.
1347 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001348 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001349 with open(dhfilename, "w") as dhfile:
1350 dhfile.write(dhparam)
1351
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001352 context.load_tmp_dh(dhfilename)
1353 # XXX What should I assert here? -exarkun
1354
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001355 def test_load_tmp_dh_bytes(self):
1356 """
1357 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1358 specified file (given as ``bytes``).
1359 """
1360 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001361 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001362 )
1363
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001364 def test_load_tmp_dh_unicode(self):
1365 """
1366 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1367 specified file (given as ``unicode``).
1368 """
1369 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001370 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001371 )
1372
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001373 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001374 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001375 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001376 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001377 """
1378 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001379 for curve in get_elliptic_curves():
1380 # The only easily "assertable" thing is that it does not raise an
1381 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001382 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001383
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001384 def test_set_cipher_list_bytes(self):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001385 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001386 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
1387 ciphers which connections created with the context object will be able
1388 to choose from.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001389 """
1390 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001391 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001392 conn = Connection(context, None)
1393 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001394
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001395 def test_set_cipher_list_text(self):
1396 """
1397 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
1398 the ciphers which connections created with the context object will be
1399 able to choose from.
1400 """
1401 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -05001402 context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001403 conn = Connection(context, None)
1404 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
1405
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001406 def test_set_cipher_list_wrong_args(self):
1407 """
Jean-Paul Calderone17044832014-01-18 10:20:11 -05001408 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
1409 passed zero arguments or more than one argument or when passed a
1410 non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001411 passed an incorrect cipher list string.
1412 """
1413 context = Context(TLSv1_METHOD)
1414 self.assertRaises(TypeError, context.set_cipher_list)
1415 self.assertRaises(TypeError, context.set_cipher_list, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001416 self.assertRaises(
1417 TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object()
1418 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001419
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001420 self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001421
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001422 def test_set_session_cache_mode_wrong_args(self):
1423 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001424 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1425 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001426 """
1427 context = Context(TLSv1_METHOD)
1428 self.assertRaises(TypeError, context.set_session_cache_mode)
1429 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1430
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001431 def test_get_session_cache_mode_wrong_args(self):
1432 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001433 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1434 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001435 """
1436 context = Context(TLSv1_METHOD)
1437 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1438
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001439 def test_session_cache_mode(self):
1440 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001441 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1442 cached. The setting can be retrieved via
1443 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001444 """
1445 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001446 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001447 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1448 self.assertEqual(SESS_CACHE_OFF, off)
1449 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1450
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001451 if not PY3:
1452 def test_session_cache_mode_long(self):
1453 """
1454 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1455 of type :py:obj:`long` as well as :py:obj:`int`.
1456 """
1457 context = Context(TLSv1_METHOD)
1458 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1459 self.assertEqual(
1460 SESS_CACHE_BOTH, context.get_session_cache_mode())
1461
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001462 def test_get_cert_store(self):
1463 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001464 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store`
1465 instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001466 """
1467 context = Context(TLSv1_METHOD)
1468 store = context.get_cert_store()
1469 self.assertIsInstance(store, X509Store)
1470
1471
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001472class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1473 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001474 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
1475 :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001476 """
1477 def test_wrong_args(self):
1478 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001479 :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001480 with other than one argument.
1481 """
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
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001487
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001488 def test_old_callback_forgotten(self):
1489 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001490 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001491 callback, the one it replaces is dereferenced.
1492 """
1493 def callback(connection):
1494 pass
1495
1496 def replacement(connection):
1497 pass
1498
1499 context = Context(TLSv1_METHOD)
1500 context.set_tlsext_servername_callback(callback)
1501
1502 tracker = ref(callback)
1503 del callback
1504
1505 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001506
1507 # One run of the garbage collector happens to work on CPython. PyPy
1508 # doesn't collect the underlying object until a second run for whatever
1509 # reason. That's fine, it still demonstrates our code has properly
1510 # dropped the reference.
1511 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001512 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001513
1514 callback = tracker()
1515 if callback is not None:
1516 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001517 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001518 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001519
1520
1521 def test_no_servername(self):
1522 """
1523 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001524 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
1525 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001526 """
1527 args = []
1528 def servername(conn):
1529 args.append((conn, conn.get_servername()))
1530 context = Context(TLSv1_METHOD)
1531 context.set_tlsext_servername_callback(servername)
1532
1533 # Lose our reference to it. The Context is responsible for keeping it
1534 # alive now.
1535 del servername
1536 collect()
1537
1538 # Necessary to actually accept the connection
1539 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1540 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1541
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
1553
1554 def test_servername(self):
1555 """
1556 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +09001557 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
1558 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001559 """
1560 args = []
1561 def servername(conn):
1562 args.append((conn, conn.get_servername()))
1563 context = Context(TLSv1_METHOD)
1564 context.set_tlsext_servername_callback(servername)
1565
1566 # Necessary to actually accept the connection
1567 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1568 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1569
1570 # Do a little connection to trigger the logic
1571 server = Connection(context, None)
1572 server.set_accept_state()
1573
1574 client = Connection(Context(TLSv1_METHOD), None)
1575 client.set_connect_state()
1576 client.set_tlsext_host_name(b("foo1.example.com"))
1577
1578 self._interactInMemory(server, client)
1579
1580 self.assertEqual([(server, b("foo1.example.com"))], args)
1581
1582
Cory Benfield84a121e2014-03-31 20:30:25 +01001583class NextProtoNegotiationTests(TestCase, _LoopbackMixin):
1584 """
1585 Test for Next Protocol Negotiation in PyOpenSSL.
1586 """
Cory Benfieldba1820d2015-04-13 17:39:12 -04001587 if _lib.Cryptography_HAS_NEXTPROTONEG:
1588 def test_npn_success(self):
1589 """
1590 Tests that clients and servers that agree on the negotiated next
1591 protocol can correct establish a connection, and that the agreed
1592 protocol is reported by the connections.
1593 """
1594 advertise_args = []
1595 select_args = []
1596 def advertise(conn):
1597 advertise_args.append((conn,))
1598 return [b'http/1.1', b'spdy/2']
1599 def select(conn, options):
1600 select_args.append((conn, options))
1601 return b'spdy/2'
Cory Benfield84a121e2014-03-31 20:30:25 +01001602
Cory Benfieldba1820d2015-04-13 17:39:12 -04001603 server_context = Context(TLSv1_METHOD)
1604 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001605
Cory Benfieldba1820d2015-04-13 17:39:12 -04001606 client_context = Context(TLSv1_METHOD)
1607 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001608
Cory Benfieldba1820d2015-04-13 17:39:12 -04001609 # Necessary to actually accept the connection
1610 server_context.use_privatekey(
1611 load_privatekey(FILETYPE_PEM, server_key_pem))
1612 server_context.use_certificate(
1613 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001614
Cory Benfieldba1820d2015-04-13 17:39:12 -04001615 # Do a little connection to trigger the logic
1616 server = Connection(server_context, None)
1617 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001618
Cory Benfieldba1820d2015-04-13 17:39:12 -04001619 client = Connection(client_context, None)
1620 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001621
Cory Benfieldba1820d2015-04-13 17:39:12 -04001622 self._interactInMemory(server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001623
Cory Benfieldba1820d2015-04-13 17:39:12 -04001624 self.assertEqual([(server,)], advertise_args)
1625 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001626
Cory Benfieldba1820d2015-04-13 17:39:12 -04001627 self.assertEqual(server.get_next_proto_negotiated(), b'spdy/2')
1628 self.assertEqual(client.get_next_proto_negotiated(), b'spdy/2')
Cory Benfield84a121e2014-03-31 20:30:25 +01001629
1630
Cory Benfieldba1820d2015-04-13 17:39:12 -04001631 def test_npn_client_fail(self):
1632 """
1633 Tests that when clients and servers cannot agree on what protocol
1634 to use next that the TLS connection does not get established.
1635 """
1636 advertise_args = []
1637 select_args = []
1638 def advertise(conn):
1639 advertise_args.append((conn,))
1640 return [b'http/1.1', b'spdy/2']
1641 def select(conn, options):
1642 select_args.append((conn, options))
1643 return b''
Cory Benfield84a121e2014-03-31 20:30:25 +01001644
Cory Benfieldba1820d2015-04-13 17:39:12 -04001645 server_context = Context(TLSv1_METHOD)
1646 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001647
Cory Benfieldba1820d2015-04-13 17:39:12 -04001648 client_context = Context(TLSv1_METHOD)
1649 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001650
Cory Benfieldba1820d2015-04-13 17:39:12 -04001651 # Necessary to actually accept the connection
1652 server_context.use_privatekey(
1653 load_privatekey(FILETYPE_PEM, server_key_pem))
1654 server_context.use_certificate(
1655 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001656
Cory Benfieldba1820d2015-04-13 17:39:12 -04001657 # Do a little connection to trigger the logic
1658 server = Connection(server_context, None)
1659 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001660
Cory Benfieldba1820d2015-04-13 17:39:12 -04001661 client = Connection(client_context, None)
1662 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001663
Cory Benfieldba1820d2015-04-13 17:39:12 -04001664 # If the client doesn't return anything, the connection will fail.
1665 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001666
Cory Benfieldba1820d2015-04-13 17:39:12 -04001667 self.assertEqual([(server,)], advertise_args)
1668 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001669
1670
Cory Benfieldba1820d2015-04-13 17:39:12 -04001671 def test_npn_select_error(self):
1672 """
1673 Test that we can handle exceptions in the select callback. If
1674 select fails it should be fatal to the connection.
1675 """
1676 advertise_args = []
1677 def advertise(conn):
1678 advertise_args.append((conn,))
1679 return [b'http/1.1', b'spdy/2']
1680 def select(conn, options):
1681 raise TypeError
Cory Benfield0ea76e72015-03-22 09:05:28 +00001682
Cory Benfieldba1820d2015-04-13 17:39:12 -04001683 server_context = Context(TLSv1_METHOD)
1684 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001685
Cory Benfieldba1820d2015-04-13 17:39:12 -04001686 client_context = Context(TLSv1_METHOD)
1687 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001688
Cory Benfieldba1820d2015-04-13 17:39:12 -04001689 # Necessary to actually accept the connection
1690 server_context.use_privatekey(
1691 load_privatekey(FILETYPE_PEM, server_key_pem))
1692 server_context.use_certificate(
1693 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001694
Cory Benfieldba1820d2015-04-13 17:39:12 -04001695 # Do a little connection to trigger the logic
1696 server = Connection(server_context, None)
1697 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001698
Cory Benfieldba1820d2015-04-13 17:39:12 -04001699 client = Connection(client_context, None)
1700 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001701
Cory Benfieldba1820d2015-04-13 17:39:12 -04001702 # If the callback throws an exception it should be raised here.
1703 self.assertRaises(
1704 TypeError, self._interactInMemory, server, client
1705 )
1706 self.assertEqual([(server,)], advertise_args)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001707
1708
Cory Benfieldba1820d2015-04-13 17:39:12 -04001709 def test_npn_advertise_error(self):
1710 """
1711 Test that we can handle exceptions in the advertise callback. If
1712 advertise fails no NPN is advertised to the client.
1713 """
1714 select_args = []
1715 def advertise(conn):
1716 raise TypeError
1717 def select(conn, options):
1718 select_args.append((conn, options))
1719 return b''
Cory Benfield0ea76e72015-03-22 09:05:28 +00001720
Cory Benfieldba1820d2015-04-13 17:39:12 -04001721 server_context = Context(TLSv1_METHOD)
1722 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001723
Cory Benfieldba1820d2015-04-13 17:39:12 -04001724 client_context = Context(TLSv1_METHOD)
1725 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001726
Cory Benfieldba1820d2015-04-13 17:39:12 -04001727 # Necessary to actually accept the connection
1728 server_context.use_privatekey(
1729 load_privatekey(FILETYPE_PEM, server_key_pem))
1730 server_context.use_certificate(
1731 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001732
Cory Benfieldba1820d2015-04-13 17:39:12 -04001733 # Do a little connection to trigger the logic
1734 server = Connection(server_context, None)
1735 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001736
Cory Benfieldba1820d2015-04-13 17:39:12 -04001737 client = Connection(client_context, None)
1738 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001739
Cory Benfieldba1820d2015-04-13 17:39:12 -04001740 # If the client doesn't return anything, the connection will fail.
1741 self.assertRaises(
1742 TypeError, self._interactInMemory, server, client
1743 )
1744 self.assertEqual([], select_args)
1745
1746 else:
1747 # No NPN.
1748 def test_npn_not_implemented(self):
1749 # Test the context methods first.
1750 context = Context(TLSv1_METHOD)
1751 fail_methods = [
1752 context.set_npn_advertise_callback,
1753 context.set_npn_select_callback,
1754 ]
1755 for method in fail_methods:
1756 self.assertRaises(
1757 NotImplementedError, method, None
1758 )
1759
1760 # Now test a connection.
1761 conn = Connection(context)
1762 fail_methods = [
1763 conn.get_next_proto_negotiated,
1764 ]
1765 for method in fail_methods:
1766 self.assertRaises(NotImplementedError, method)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001767
1768
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001769
Cory Benfield12eae892014-06-07 15:42:56 +01001770class ApplicationLayerProtoNegotiationTests(TestCase, _LoopbackMixin):
1771 """
1772 Tests for ALPN in PyOpenSSL.
1773 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001774 # Skip tests on versions that don't support ALPN.
1775 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001776
Cory Benfielde46fa842015-04-13 16:50:49 -04001777 def test_alpn_success(self):
1778 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001779 Clients and servers that agree on the negotiated ALPN protocol can
1780 correct establish a connection, and the agreed protocol is reported
1781 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001782 """
1783 select_args = []
1784 def select(conn, options):
1785 select_args.append((conn, options))
1786 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001787
Cory Benfielde46fa842015-04-13 16:50:49 -04001788 client_context = Context(TLSv1_METHOD)
1789 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001790
Cory Benfielde46fa842015-04-13 16:50:49 -04001791 server_context = Context(TLSv1_METHOD)
1792 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001793
Cory Benfielde46fa842015-04-13 16:50:49 -04001794 # Necessary to actually accept the connection
1795 server_context.use_privatekey(
1796 load_privatekey(FILETYPE_PEM, server_key_pem))
1797 server_context.use_certificate(
1798 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001799
Cory Benfielde46fa842015-04-13 16:50:49 -04001800 # Do a little connection to trigger the logic
1801 server = Connection(server_context, None)
1802 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001803
Cory Benfielde46fa842015-04-13 16:50:49 -04001804 client = Connection(client_context, None)
1805 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001806
Cory Benfielde46fa842015-04-13 16:50:49 -04001807 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001808
Cory Benfielde46fa842015-04-13 16:50:49 -04001809 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
1810
1811 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1812 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001813
1814
Cory Benfielde46fa842015-04-13 16:50:49 -04001815 def test_alpn_set_on_connection(self):
1816 """
1817 The same as test_alpn_success, but setting the ALPN protocols on
1818 the connection rather than the context.
1819 """
1820 select_args = []
1821 def select(conn, options):
1822 select_args.append((conn, options))
1823 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001824
Cory Benfielde46fa842015-04-13 16:50:49 -04001825 # Setup the client context but don't set any ALPN protocols.
1826 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001827
Cory Benfielde46fa842015-04-13 16:50:49 -04001828 server_context = Context(TLSv1_METHOD)
1829 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001830
Cory Benfielde46fa842015-04-13 16:50:49 -04001831 # Necessary to actually accept the connection
1832 server_context.use_privatekey(
1833 load_privatekey(FILETYPE_PEM, server_key_pem))
1834 server_context.use_certificate(
1835 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001836
Cory Benfielde46fa842015-04-13 16:50:49 -04001837 # Do a little connection to trigger the logic
1838 server = Connection(server_context, None)
1839 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001840
Cory Benfielde46fa842015-04-13 16:50:49 -04001841 # Set the ALPN protocols on the client connection.
1842 client = Connection(client_context, None)
1843 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1844 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001845
Cory Benfielde46fa842015-04-13 16:50:49 -04001846 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001847
Cory Benfielde46fa842015-04-13 16:50:49 -04001848 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001849
Cory Benfielde46fa842015-04-13 16:50:49 -04001850 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1851 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001852
1853
Cory Benfielde46fa842015-04-13 16:50:49 -04001854 def test_alpn_server_fail(self):
1855 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001856 When clients and servers cannot agree on what protocol to use next
1857 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001858 """
1859 select_args = []
1860 def select(conn, options):
1861 select_args.append((conn, options))
1862 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001863
Cory Benfielde46fa842015-04-13 16:50:49 -04001864 client_context = Context(TLSv1_METHOD)
1865 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001866
Cory Benfielde46fa842015-04-13 16:50:49 -04001867 server_context = Context(TLSv1_METHOD)
1868 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001869
Cory Benfielde46fa842015-04-13 16:50:49 -04001870 # Necessary to actually accept the connection
1871 server_context.use_privatekey(
1872 load_privatekey(FILETYPE_PEM, server_key_pem))
1873 server_context.use_certificate(
1874 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001875
Cory Benfielde46fa842015-04-13 16:50:49 -04001876 # Do a little connection to trigger the logic
1877 server = Connection(server_context, None)
1878 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001879
Cory Benfielde46fa842015-04-13 16:50:49 -04001880 client = Connection(client_context, None)
1881 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001882
Cory Benfielde46fa842015-04-13 16:50:49 -04001883 # If the client doesn't return anything, the connection will fail.
1884 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001885
Cory Benfielde46fa842015-04-13 16:50:49 -04001886 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001887
1888
Cory Benfielde46fa842015-04-13 16:50:49 -04001889 def test_alpn_no_server(self):
1890 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001891 When clients and servers cannot agree on what protocol to use next
1892 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04001893 """
1894 client_context = Context(TLSv1_METHOD)
1895 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04001896
Cory Benfielde46fa842015-04-13 16:50:49 -04001897 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04001898
Cory Benfielde46fa842015-04-13 16:50:49 -04001899 # Necessary to actually accept the connection
1900 server_context.use_privatekey(
1901 load_privatekey(FILETYPE_PEM, server_key_pem))
1902 server_context.use_certificate(
1903 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04001904
Cory Benfielde46fa842015-04-13 16:50:49 -04001905 # Do a little connection to trigger the logic
1906 server = Connection(server_context, None)
1907 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001908
Cory Benfielde46fa842015-04-13 16:50:49 -04001909 client = Connection(client_context, None)
1910 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001911
Cory Benfielde46fa842015-04-13 16:50:49 -04001912 # Do the dance.
1913 self._interactInMemory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04001914
Cory Benfielde46fa842015-04-13 16:50:49 -04001915 self.assertEqual(client.get_alpn_proto_negotiated(), b'')
Cory Benfielde3d57152015-04-11 17:57:35 -04001916
1917
Cory Benfielde46fa842015-04-13 16:50:49 -04001918 def test_alpn_callback_exception(self):
1919 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001920 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04001921 """
1922 select_args = []
1923 def select(conn, options):
1924 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04001925 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001926
Cory Benfielde46fa842015-04-13 16:50:49 -04001927 client_context = Context(TLSv1_METHOD)
1928 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04001929
Cory Benfielde46fa842015-04-13 16:50:49 -04001930 server_context = Context(TLSv1_METHOD)
1931 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04001932
Cory Benfielde46fa842015-04-13 16:50:49 -04001933 # Necessary to actually accept the connection
1934 server_context.use_privatekey(
1935 load_privatekey(FILETYPE_PEM, server_key_pem))
1936 server_context.use_certificate(
1937 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04001938
Cory Benfielde46fa842015-04-13 16:50:49 -04001939 # Do a little connection to trigger the logic
1940 server = Connection(server_context, None)
1941 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001942
Cory Benfielde46fa842015-04-13 16:50:49 -04001943 client = Connection(client_context, None)
1944 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001945
Cory Benfielde46fa842015-04-13 16:50:49 -04001946 self.assertRaises(
1947 TypeError, self._interactInMemory, server, client
1948 )
1949 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfieldf1177e72015-04-12 09:11:49 -04001950
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001951 else:
1952 # No ALPN.
1953 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04001954 """
1955 If ALPN is not in OpenSSL, we should raise NotImplementedError.
1956 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001957 # Test the context methods first.
1958 context = Context(TLSv1_METHOD)
Cory Benfield307e9e62015-04-13 18:21:12 -04001959 self.assertRaises(
1960 NotImplementedError, context.set_alpn_protos, None
1961 )
1962 self.assertRaises(
1963 NotImplementedError, context.set_alpn_select_callback, None
1964 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001965
1966 # Now test a connection.
1967 conn = Connection(context)
Cory Benfield307e9e62015-04-13 18:21:12 -04001968 self.assertRaises(
Alex Gaynor68417232015-09-04 07:56:29 -04001969 NotImplementedError, conn.set_alpn_protos, None
Cory Benfield307e9e62015-04-13 18:21:12 -04001970 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001971
Cory Benfieldf1177e72015-04-12 09:11:49 -04001972
Cory Benfield12eae892014-06-07 15:42:56 +01001973
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001974class SessionTests(TestCase):
1975 """
1976 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1977 """
1978 def test_construction(self):
1979 """
1980 :py:class:`Session` can be constructed with no arguments, creating a new
1981 instance of that type.
1982 """
1983 new_session = Session()
1984 self.assertTrue(isinstance(new_session, Session))
1985
1986
1987 def test_construction_wrong_args(self):
1988 """
1989 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
1990 is raised.
1991 """
1992 self.assertRaises(TypeError, Session, 123)
1993 self.assertRaises(TypeError, Session, "hello")
1994 self.assertRaises(TypeError, Session, object())
1995
1996
1997
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001998class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05001999 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002000 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002001 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002002 # XXX get_peer_certificate -> None
2003 # XXX sock_shutdown
2004 # XXX master_key -> TypeError
2005 # XXX server_random -> TypeError
2006 # XXX state_string
2007 # XXX connect -> TypeError
2008 # XXX connect_ex -> TypeError
2009 # XXX set_connect_state -> TypeError
2010 # XXX set_accept_state -> TypeError
2011 # XXX renegotiate_pending
2012 # XXX do_handshake -> TypeError
2013 # XXX bio_read -> TypeError
2014 # XXX recv -> TypeError
2015 # XXX send -> TypeError
2016 # XXX bio_write -> TypeError
2017
Rick Deane15b1472009-07-09 15:53:42 -05002018 def test_type(self):
2019 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002020 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002021 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002022 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002023 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05002024 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002025 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002026
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002027
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002028 def test_get_context(self):
2029 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002030 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
2031 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002032 """
2033 context = Context(TLSv1_METHOD)
2034 connection = Connection(context, None)
2035 self.assertIdentical(connection.get_context(), context)
2036
2037
2038 def test_get_context_wrong_args(self):
2039 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002040 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002041 arguments.
2042 """
2043 connection = Connection(Context(TLSv1_METHOD), None)
2044 self.assertRaises(TypeError, connection.get_context, None)
2045
2046
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002047 def test_set_context_wrong_args(self):
2048 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002049 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
2050 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002051 than 1.
2052 """
2053 ctx = Context(TLSv1_METHOD)
2054 connection = Connection(ctx, None)
2055 self.assertRaises(TypeError, connection.set_context)
2056 self.assertRaises(TypeError, connection.set_context, object())
2057 self.assertRaises(TypeError, connection.set_context, "hello")
2058 self.assertRaises(TypeError, connection.set_context, 1)
2059 self.assertRaises(TypeError, connection.set_context, 1, 2)
2060 self.assertRaises(
2061 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
2062 self.assertIdentical(ctx, connection.get_context())
2063
2064
2065 def test_set_context(self):
2066 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002067 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002068 for the connection.
2069 """
2070 original = Context(SSLv23_METHOD)
2071 replacement = Context(TLSv1_METHOD)
2072 connection = Connection(original, None)
2073 connection.set_context(replacement)
2074 self.assertIdentical(replacement, connection.get_context())
2075 # Lose our references to the contexts, just in case the Connection isn't
2076 # properly managing its own contributions to their reference counts.
2077 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002078 collect()
2079
2080
2081 def test_set_tlsext_host_name_wrong_args(self):
2082 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002083 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002084 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09002085 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002086 """
2087 conn = Connection(Context(TLSv1_METHOD), None)
2088 self.assertRaises(TypeError, conn.set_tlsext_host_name)
2089 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
2090 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
2091 self.assertRaises(
2092 TypeError, conn.set_tlsext_host_name, b("with\0null"))
2093
Abraham Martinc5484ba2015-03-25 15:33:05 +00002094 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002095 # On Python 3.x, don't accidentally implicitly convert from text.
2096 self.assertRaises(
2097 TypeError,
2098 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002099
2100
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002101 def test_get_servername_wrong_args(self):
2102 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002103 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002104 arguments.
2105 """
2106 connection = Connection(Context(TLSv1_METHOD), None)
2107 self.assertRaises(TypeError, connection.get_servername, object())
2108 self.assertRaises(TypeError, connection.get_servername, 1)
2109 self.assertRaises(TypeError, connection.get_servername, "hello")
2110
2111
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002112 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002113 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002114 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002115 immediate read.
2116 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002117 connection = Connection(Context(TLSv1_METHOD), None)
2118 self.assertEquals(connection.pending(), 0)
2119
2120
2121 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002122 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002123 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002124 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002125 connection = Connection(Context(TLSv1_METHOD), None)
2126 self.assertRaises(TypeError, connection.pending, None)
2127
2128
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002129 def test_peek(self):
2130 """
2131 :py:obj:`Connection.recv` peeks into the connection if :py:obj:`socket.MSG_PEEK` is passed.
2132 """
2133 server, client = self._loopback()
2134 server.send(b('xy'))
2135 self.assertEqual(client.recv(2, MSG_PEEK), b('xy'))
2136 self.assertEqual(client.recv(2, MSG_PEEK), b('xy'))
2137 self.assertEqual(client.recv(2), b('xy'))
2138
2139
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002140 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002141 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002142 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002143 argument or with the wrong number of arguments.
2144 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002145 connection = Connection(Context(TLSv1_METHOD), socket())
2146 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002147 self.assertRaises(TypeError, connection.connect)
2148 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002149
kjavfe508d62015-09-02 12:20:35 +01002150 def test_connection_undefined_attr(self):
2151 """
2152 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
2153 argument or with the wrong number of arguments.
2154 """
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002155
kjavfe508d62015-09-02 12:20:35 +01002156 def attr_access_test(connection):
2157 return connection.an_attribute_which_is_not_defined
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002158
kjavfe508d62015-09-02 12:20:35 +01002159 connection = Connection(Context(TLSv1_METHOD), None)
2160 self.assertRaises(AttributeError, attr_access_test, connection)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002161
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002162 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002163 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002164 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002165 connect method raises it.
2166 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002167 client = socket()
2168 context = Context(TLSv1_METHOD)
2169 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002170 # pytest.raises here doesn't work because of a bug in py.test on Python
2171 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002172 try:
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002173 clientSSL.connect(("127.0.0.1", 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002174 except error as e:
2175 pass
2176 assert e.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002177
2178 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002179 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002180 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002181 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002182 port = socket()
2183 port.bind(('', 0))
2184 port.listen(3)
2185
2186 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002187 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2188 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002189
2190
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002191 if platform == "darwin":
2192 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2193 else:
2194 def test_connect_ex(self):
2195 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002196 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002197 errno instead of raising an exception.
2198 """
2199 port = socket()
2200 port.bind(('', 0))
2201 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002202
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002203 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2204 clientSSL.setblocking(False)
2205 result = clientSSL.connect_ex(port.getsockname())
2206 expected = (EINPROGRESS, EWOULDBLOCK)
2207 self.assertTrue(
2208 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002209
2210
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002211 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002212 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002213 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002214 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002215 connection = Connection(Context(TLSv1_METHOD), socket())
2216 self.assertRaises(TypeError, connection.accept, None)
2217
2218
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002219 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002220 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002221 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
2222 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002223 connection originated from.
2224 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002225 ctx = Context(TLSv1_METHOD)
2226 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2227 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002228 port = socket()
2229 portSSL = Connection(ctx, port)
2230 portSSL.bind(('', 0))
2231 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002232
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002233 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002234
2235 # Calling portSSL.getsockname() here to get the server IP address sounds
2236 # great, but frequently fails on Windows.
2237 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002238
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002239 serverSSL, address = portSSL.accept()
2240
2241 self.assertTrue(isinstance(serverSSL, Connection))
2242 self.assertIdentical(serverSSL.get_context(), ctx)
2243 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002244
2245
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002246 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002247 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002248 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002249 number of arguments or with arguments other than integers.
2250 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002251 connection = Connection(Context(TLSv1_METHOD), None)
2252 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04002253 self.assertRaises(TypeError, connection.get_shutdown, None)
2254 self.assertRaises(TypeError, connection.set_shutdown)
2255 self.assertRaises(TypeError, connection.set_shutdown, None)
2256 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002257
2258
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002259 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002260 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002261 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002262 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002263 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002264 self.assertFalse(server.shutdown())
2265 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002266 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002267 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
2268 client.shutdown()
Alex Gaynor43307782015-09-04 09:05:45 -04002269 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002270 self.assertRaises(ZeroReturnError, server.recv, 1024)
Alex Gaynor43307782015-09-04 09:05:45 -04002271 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002272
2273
Paul Aurichc85e0862015-01-08 08:34:33 -08002274 def test_shutdown_closed(self):
2275 """
2276 If the underlying socket is closed, :py:obj:`Connection.shutdown` propagates the
2277 write error from the low level write call.
2278 """
2279 server, client = self._loopback()
2280 server.sock_shutdown(2)
2281 exc = self.assertRaises(SysCallError, server.shutdown)
2282 if platform == "win32":
2283 self.assertEqual(exc.args[0], ESHUTDOWN)
2284 else:
2285 self.assertEqual(exc.args[0], EPIPE)
2286
2287
Glyph89389472015-04-14 17:29:26 -04002288 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002289 """
Glyph89389472015-04-14 17:29:26 -04002290 If the underlying connection is truncated, :obj:`Connection.shutdown`
2291 raises an :obj:`Error`.
Glyph6064ec32015-04-14 16:38:22 -04002292 """
Glyph89389472015-04-14 17:29:26 -04002293 server_ctx = Context(TLSv1_METHOD)
2294 client_ctx = Context(TLSv1_METHOD)
2295 server_ctx.use_privatekey(
2296 load_privatekey(FILETYPE_PEM, server_key_pem))
2297 server_ctx.use_certificate(
2298 load_certificate(FILETYPE_PEM, server_cert_pem))
2299 server = Connection(server_ctx, None)
2300 client = Connection(client_ctx, None)
2301 self._handshakeInMemory(client, server)
2302 self.assertEqual(server.shutdown(), False)
2303 self.assertRaises(WantReadError, server.shutdown)
2304 server.bio_shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002305 self.assertRaises(Error, server.shutdown)
2306
2307
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002308 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002309 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002310 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002311 process.
2312 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002313 connection = Connection(Context(TLSv1_METHOD), socket())
2314 connection.set_shutdown(RECEIVED_SHUTDOWN)
2315 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2316
2317
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002318 if not PY3:
2319 def test_set_shutdown_long(self):
2320 """
2321 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
2322 of type :py:obj:`long` as well as :py:obj:`int`.
2323 """
2324 connection = Connection(Context(TLSv1_METHOD), socket())
2325 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
2326 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2327
2328
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002329 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002330 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002331 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
2332 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002333 with any arguments.
2334 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002335 conn = Connection(Context(TLSv1_METHOD), None)
2336 self.assertRaises(TypeError, conn.get_app_data, None)
2337 self.assertRaises(TypeError, conn.set_app_data)
2338 self.assertRaises(TypeError, conn.set_app_data, None, None)
2339
2340
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002341 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002342 """
2343 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002344 :py:obj:`Connection.set_app_data` and later retrieved with
2345 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002346 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002347 conn = Connection(Context(TLSv1_METHOD), None)
2348 app_data = object()
2349 conn.set_app_data(app_data)
2350 self.assertIdentical(conn.get_app_data(), app_data)
2351
2352
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002353 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002354 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002355 :py:obj:`Connection.makefile` is not implemented and calling that method raises
2356 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002357 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002358 conn = Connection(Context(TLSv1_METHOD), None)
2359 self.assertRaises(NotImplementedError, conn.makefile)
2360
2361
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002362 def test_get_peer_cert_chain_wrong_args(self):
2363 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002364 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002365 arguments.
2366 """
2367 conn = Connection(Context(TLSv1_METHOD), None)
2368 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
2369 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
2370 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
2371 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
2372
2373
2374 def test_get_peer_cert_chain(self):
2375 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002376 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002377 the connected server returned for the certification verification.
2378 """
2379 chain = _create_certificate_chain()
2380 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2381
2382 serverContext = Context(TLSv1_METHOD)
2383 serverContext.use_privatekey(skey)
2384 serverContext.use_certificate(scert)
2385 serverContext.add_extra_chain_cert(icert)
2386 serverContext.add_extra_chain_cert(cacert)
2387 server = Connection(serverContext, None)
2388 server.set_accept_state()
2389
2390 # Create the client
2391 clientContext = Context(TLSv1_METHOD)
2392 clientContext.set_verify(VERIFY_NONE, verify_cb)
2393 client = Connection(clientContext, None)
2394 client.set_connect_state()
2395
2396 self._interactInMemory(client, server)
2397
2398 chain = client.get_peer_cert_chain()
2399 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002400 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002401 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002402 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002403 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002404 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002405 "Authority Certificate", chain[2].get_subject().CN)
2406
2407
2408 def test_get_peer_cert_chain_none(self):
2409 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002410 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002411 certificate chain.
2412 """
2413 ctx = Context(TLSv1_METHOD)
2414 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2415 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2416 server = Connection(ctx, None)
2417 server.set_accept_state()
2418 client = Connection(Context(TLSv1_METHOD), None)
2419 client.set_connect_state()
2420 self._interactInMemory(client, server)
2421 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002422
2423
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002424 def test_get_session_wrong_args(self):
2425 """
2426 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
2427 with any arguments.
2428 """
2429 ctx = Context(TLSv1_METHOD)
2430 server = Connection(ctx, None)
2431 self.assertRaises(TypeError, server.get_session, 123)
2432 self.assertRaises(TypeError, server.get_session, "hello")
2433 self.assertRaises(TypeError, server.get_session, object())
2434
2435
2436 def test_get_session_unconnected(self):
2437 """
2438 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
2439 an object which has not been connected.
2440 """
2441 ctx = Context(TLSv1_METHOD)
2442 server = Connection(ctx, None)
2443 session = server.get_session()
2444 self.assertIdentical(None, session)
2445
2446
2447 def test_server_get_session(self):
2448 """
2449 On the server side of a connection, :py:obj:`Connection.get_session`
2450 returns a :py:class:`Session` instance representing the SSL session for
2451 that connection.
2452 """
2453 server, client = self._loopback()
2454 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002455 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002456
2457
2458 def test_client_get_session(self):
2459 """
2460 On the client side of a connection, :py:obj:`Connection.get_session`
2461 returns a :py:class:`Session` instance representing the SSL session for
2462 that connection.
2463 """
2464 server, client = self._loopback()
2465 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002466 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002467
2468
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002469 def test_set_session_wrong_args(self):
2470 """
2471 If called with an object that is not an instance of :py:class:`Session`,
2472 or with other than one argument, :py:obj:`Connection.set_session` raises
2473 :py:obj:`TypeError`.
2474 """
2475 ctx = Context(TLSv1_METHOD)
2476 connection = Connection(ctx, None)
2477 self.assertRaises(TypeError, connection.set_session)
2478 self.assertRaises(TypeError, connection.set_session, 123)
2479 self.assertRaises(TypeError, connection.set_session, "hello")
2480 self.assertRaises(TypeError, connection.set_session, object())
2481 self.assertRaises(
2482 TypeError, connection.set_session, Session(), Session())
2483
2484
2485 def test_client_set_session(self):
2486 """
2487 :py:obj:`Connection.set_session`, when used prior to a connection being
2488 established, accepts a :py:class:`Session` instance and causes an
2489 attempt to re-use the session it represents when the SSL handshake is
2490 performed.
2491 """
2492 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2493 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2494 ctx = Context(TLSv1_METHOD)
2495 ctx.use_privatekey(key)
2496 ctx.use_certificate(cert)
2497 ctx.set_session_id("unity-test")
2498
2499 def makeServer(socket):
2500 server = Connection(ctx, socket)
2501 server.set_accept_state()
2502 return server
2503
2504 originalServer, originalClient = self._loopback(
2505 serverFactory=makeServer)
2506 originalSession = originalClient.get_session()
2507
2508 def makeClient(socket):
2509 client = self._loopbackClientFactory(socket)
2510 client.set_session(originalSession)
2511 return client
2512 resumedServer, resumedClient = self._loopback(
2513 serverFactory=makeServer,
2514 clientFactory=makeClient)
2515
2516 # This is a proxy: in general, we have no access to any unique
2517 # identifier for the session (new enough versions of OpenSSL expose a
2518 # hash which could be usable, but "new enough" is very, very new).
2519 # Instead, exploit the fact that the master key is re-used if the
2520 # session is re-used. As long as the master key for the two connections
2521 # is the same, the session was re-used!
2522 self.assertEqual(
2523 originalServer.master_key(), resumedServer.master_key())
2524
2525
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002526 def test_set_session_wrong_method(self):
2527 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002528 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
2529 instance associated with a context using a different SSL method than the
2530 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
2531 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002532 """
2533 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2534 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2535 ctx = Context(TLSv1_METHOD)
2536 ctx.use_privatekey(key)
2537 ctx.use_certificate(cert)
2538 ctx.set_session_id("unity-test")
2539
2540 def makeServer(socket):
2541 server = Connection(ctx, socket)
2542 server.set_accept_state()
2543 return server
2544
2545 originalServer, originalClient = self._loopback(
2546 serverFactory=makeServer)
2547 originalSession = originalClient.get_session()
2548
2549 def makeClient(socket):
2550 # Intentionally use a different, incompatible method here.
2551 client = Connection(Context(SSLv3_METHOD), socket)
2552 client.set_connect_state()
2553 client.set_session(originalSession)
2554 return client
2555
2556 self.assertRaises(
2557 Error,
2558 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2559
2560
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002561 def test_wantWriteError(self):
2562 """
2563 :py:obj:`Connection` methods which generate output raise
2564 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2565 fail indicating a should-write state.
2566 """
2567 client_socket, server_socket = socket_pair()
2568 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002569 # anything. Only write a single byte at a time so we can be sure we
2570 # completely fill the buffer. Even though the socket API is allowed to
2571 # signal a short write via its return value it seems this doesn't
2572 # always happen on all platforms (FreeBSD and OS X particular) for the
2573 # very last bit of available buffer space.
2574 msg = b"x"
2575 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002576 try:
2577 client_socket.send(msg)
2578 except error as e:
2579 if e.errno == EWOULDBLOCK:
2580 break
2581 raise
2582 else:
2583 self.fail(
2584 "Failed to fill socket buffer, cannot test BIO want write")
2585
2586 ctx = Context(TLSv1_METHOD)
2587 conn = Connection(ctx, client_socket)
2588 # Client's speak first, so make it an SSL client
2589 conn.set_connect_state()
2590 self.assertRaises(WantWriteError, conn.do_handshake)
2591
2592 # XXX want_read
2593
Fedor Brunner416f4a12014-03-28 13:18:38 +01002594 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002595 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002596 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2597 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002598 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002599 ctx = Context(TLSv1_METHOD)
2600 connection = Connection(ctx, None)
2601 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002602
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002603
Fedor Brunner416f4a12014-03-28 13:18:38 +01002604 def test_get_peer_finished_before_connect(self):
2605 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002606 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2607 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002608 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002609 ctx = Context(TLSv1_METHOD)
2610 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002611 self.assertEqual(connection.get_peer_finished(), None)
2612
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002613
Fedor Brunner416f4a12014-03-28 13:18:38 +01002614 def test_get_finished(self):
2615 """
2616 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002617 message send from client, or server. Finished messages are send during
2618 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002619 """
2620
Fedor Brunner5747b932014-03-05 14:22:34 +01002621 server, client = self._loopback()
2622
2623 self.assertNotEqual(server.get_finished(), None)
2624 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002625
Jean-Paul Calderoned979f232014-03-30 11:58:00 -04002626
Fedor Brunner416f4a12014-03-28 13:18:38 +01002627 def test_get_peer_finished(self):
2628 """
2629 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002630 message received from client, or server. Finished messages are send
2631 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002632 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002633 server, client = self._loopback()
2634
2635 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002636 self.assertTrue(len(server.get_peer_finished()) > 0)
2637
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002638
Fedor Brunner416f4a12014-03-28 13:18:38 +01002639 def test_tls_finished_message_symmetry(self):
2640 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002641 The TLS Finished message send by server must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002642 received by client.
2643
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002644 The TLS Finished message send by client must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002645 received by server.
2646 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002647 server, client = self._loopback()
2648
Fedor Brunner5747b932014-03-05 14:22:34 +01002649 self.assertEqual(server.get_finished(), client.get_peer_finished())
2650 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002651
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002652
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002653 def test_get_cipher_name_before_connect(self):
2654 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002655 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2656 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002657 """
2658 ctx = Context(TLSv1_METHOD)
2659 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002660 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002661
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002662
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002663 def test_get_cipher_name(self):
2664 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002665 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2666 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002667 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002668 server, client = self._loopback()
2669 server_cipher_name, client_cipher_name = \
2670 server.get_cipher_name(), client.get_cipher_name()
2671
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002672 self.assertIsInstance(server_cipher_name, text_type)
2673 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002674
2675 self.assertEqual(server_cipher_name, client_cipher_name)
2676
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002677
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002678 def test_get_cipher_version_before_connect(self):
2679 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002680 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2681 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002682 """
2683 ctx = Context(TLSv1_METHOD)
2684 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002685 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002686
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002687
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002688 def test_get_cipher_version(self):
2689 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002690 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2691 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002692 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002693 server, client = self._loopback()
2694 server_cipher_version, client_cipher_version = \
2695 server.get_cipher_version(), client.get_cipher_version()
2696
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002697 self.assertIsInstance(server_cipher_version, text_type)
2698 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002699
2700 self.assertEqual(server_cipher_version, client_cipher_version)
2701
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002702
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002703 def test_get_cipher_bits_before_connect(self):
2704 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002705 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2706 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002707 """
2708 ctx = Context(TLSv1_METHOD)
2709 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002710 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002711
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002712
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002713 def test_get_cipher_bits(self):
2714 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002715 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2716 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002717 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002718 server, client = self._loopback()
2719 server_cipher_bits, client_cipher_bits = \
2720 server.get_cipher_bits(), client.get_cipher_bits()
2721
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002722 self.assertIsInstance(server_cipher_bits, int)
2723 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002724
2725 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002726
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002727
Jim Shaverabff1882015-05-27 09:15:55 -04002728 def test_get_protocol_version_name(self):
2729 """
2730 :py:obj:`Connection.get_protocol_version_name()` returns a string
2731 giving the protocol version of the current connection.
2732 """
2733 server, client = self._loopback()
2734 client_protocol_version_name = client.get_protocol_version_name()
2735 server_protocol_version_name = server.get_protocol_version_name()
2736
Jim Shaver58d25732015-05-28 11:52:32 -04002737 self.assertIsInstance(server_protocol_version_name, text_type)
2738 self.assertIsInstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002739
2740 self.assertEqual(server_protocol_version_name, client_protocol_version_name)
2741
2742
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002743 def test_get_protocol_version(self):
2744 """
Alex Gaynor43307782015-09-04 09:05:45 -04002745 :py:obj:`Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002746 giving the protocol version of the current connection.
2747 """
2748 server, client = self._loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002749 client_protocol_version = client.get_protocol_version()
2750 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002751
Jim Shaverabff1882015-05-27 09:15:55 -04002752 self.assertIsInstance(server_protocol_version, int)
2753 self.assertIsInstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002754
2755 self.assertEqual(server_protocol_version, client_protocol_version)
2756
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002757
Jim Shaver208438c2015-05-28 09:52:38 -04002758
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002759class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002760 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002761 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002762 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002763 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002764 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002765 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002766 arguments.
2767 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002768 connection = Connection(Context(TLSv1_METHOD), None)
2769 self.assertRaises(TypeError, connection.get_cipher_list, None)
2770
2771
2772 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002773 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002774 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2775 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002776 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002777 connection = Connection(Context(TLSv1_METHOD), None)
2778 ciphers = connection.get_cipher_list()
2779 self.assertTrue(isinstance(ciphers, list))
2780 for cipher in ciphers:
2781 self.assertTrue(isinstance(cipher, str))
2782
2783
2784
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002785class ConnectionSendTests(TestCase, _LoopbackMixin):
2786 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002787 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002788 """
2789 def test_wrong_args(self):
2790 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002791 When called with arguments other than string argument for its first
2792 parameter or more than two arguments, :py:obj:`Connection.send` raises
2793 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002794 """
2795 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002796 self.assertRaises(TypeError, connection.send)
2797 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002798 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002799
2800
2801 def test_short_bytes(self):
2802 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002803 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002804 and returns the number of bytes sent.
2805 """
2806 server, client = self._loopback()
2807 count = server.send(b('xy'))
2808 self.assertEquals(count, 2)
2809 self.assertEquals(client.recv(2), b('xy'))
2810
Abraham Martinef063482015-03-25 14:06:24 +00002811
2812 def test_text(self):
2813 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002814 When passed a text, :py:obj:`Connection.send` transmits all of it and
2815 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002816 """
2817 server, client = self._loopback()
2818 with catch_warnings(record=True) as w:
2819 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002820 count = server.send(b"xy".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002821 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002822 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002823 WARNING_TYPE_EXPECTED
2824 ),
2825 str(w[-1].message)
2826 )
2827 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinef063482015-03-25 14:06:24 +00002828 self.assertEquals(count, 2)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002829 self.assertEquals(client.recv(2), b"xy")
Abraham Martinef063482015-03-25 14:06:24 +00002830
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002831 try:
2832 memoryview
2833 except NameError:
2834 "cannot test sending memoryview without memoryview"
2835 else:
2836 def test_short_memoryview(self):
2837 """
2838 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002839 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002840 bytes sent.
2841 """
2842 server, client = self._loopback()
2843 count = server.send(memoryview(b('xy')))
2844 self.assertEquals(count, 2)
2845 self.assertEquals(client.recv(2), b('xy'))
2846
2847
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002848 try:
2849 buffer
2850 except NameError:
2851 "cannot test sending buffer without buffer"
2852 else:
2853 def test_short_buffer(self):
2854 """
2855 When passed a buffer containing a small number of bytes,
2856 :py:obj:`Connection.send` transmits all of them and returns the number of
2857 bytes sent.
2858 """
2859 server, client = self._loopback()
2860 count = server.send(buffer(b('xy')))
2861 self.assertEquals(count, 2)
2862 self.assertEquals(client.recv(2), b('xy'))
2863
2864
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002865
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002866def _make_memoryview(size):
2867 """
2868 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2869 size.
2870 """
2871 return memoryview(bytearray(size))
2872
2873
2874
Cory Benfield62d10332014-06-15 10:03:41 +01002875class ConnectionRecvIntoTests(TestCase, _LoopbackMixin):
2876 """
2877 Tests for :py:obj:`Connection.recv_into`
2878 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002879 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002880 """
2881 Assert that when the given buffer is passed to
2882 ``Connection.recv_into``, whatever bytes are available to be received
2883 that fit into that buffer are written into that buffer.
2884 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002885 output_buffer = factory(5)
2886
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002887 server, client = self._loopback()
2888 server.send(b('xy'))
2889
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002890 self.assertEqual(client.recv_into(output_buffer), 2)
2891 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002892
2893
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002894 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002895 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002896 :py:obj:`Connection.recv_into` can be passed a ``bytearray`` instance
2897 and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002898 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002899 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002900
2901
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002902 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002903 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002904 Assert that when the given buffer is passed to ``Connection.recv_into``
2905 along with a value for ``nbytes`` that is less than the size of that
2906 buffer, only ``nbytes`` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002907 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002908 output_buffer = factory(10)
2909
Cory Benfield62d10332014-06-15 10:03:41 +01002910 server, client = self._loopback()
2911 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002912
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002913 self.assertEqual(client.recv_into(output_buffer, 5), 5)
2914 self.assertEqual(
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002915 output_buffer, bytearray(b('abcde\x00\x00\x00\x00\x00'))
2916 )
2917
2918
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002919 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002920 """
2921 When called with a ``bytearray`` instance,
2922 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter and
2923 doesn't copy in more than that number of bytes.
2924 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002925 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002926
2927
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002928 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002929 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002930 Assert that if there are more bytes available to be read from the
2931 receive buffer than would fit into the buffer passed to
2932 :py:obj:`Connection.recv_into`, only as many as fit are written into
2933 it.
Cory Benfield62d10332014-06-15 10:03:41 +01002934 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002935 output_buffer = factory(5)
2936
Cory Benfield62d10332014-06-15 10:03:41 +01002937 server, client = self._loopback()
2938 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002939
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002940 self.assertEqual(client.recv_into(output_buffer), 5)
2941 self.assertEqual(output_buffer, bytearray(b('abcde')))
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002942 rest = client.recv(5)
2943 self.assertEqual(b('fghij'), rest)
2944
2945
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002946 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002947 """
2948 When called with a ``bytearray`` instance,
2949 :py:obj:`Connection.recv_into` respects the size of the array and
2950 doesn't write more bytes into it than will fit.
2951 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002952 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002953
2954
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002955 def _really_doesnt_overfill_test(self, factory):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002956 """
2957 Assert that if the value given by ``nbytes`` is greater than the actual
2958 size of the output buffer passed to :py:obj:`Connection.recv_into`, the
2959 behavior is as if no value was given for ``nbytes`` at all.
2960 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002961 output_buffer = factory(5)
2962
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002963 server, client = self._loopback()
2964 server.send(b('abcdefghij'))
2965
2966 self.assertEqual(client.recv_into(output_buffer, 50), 5)
2967 self.assertEqual(output_buffer, bytearray(b('abcde')))
2968 rest = client.recv(5)
2969 self.assertEqual(b('fghij'), rest)
2970
2971
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002972 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002973 """
2974 When called with a ``bytearray`` instance and an ``nbytes`` value that
2975 is too large, :py:obj:`Connection.recv_into` respects the size of the
2976 array and not the ``nbytes`` value and doesn't write more bytes into
2977 the buffer than will fit.
2978 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002979 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002980
2981
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002982 def test_peek(self):
2983
2984 server, client = self._loopback()
2985 server.send(b('xy'))
2986
2987 for _ in range(2):
2988 output_buffer = bytearray(5)
2989 self.assertEqual(client.recv_into(output_buffer, flags=MSG_PEEK), 2)
2990 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
2991
2992
Cory Benfield62d10332014-06-15 10:03:41 +01002993 try:
2994 memoryview
2995 except NameError:
2996 "cannot test recv_into memoryview without memoryview"
2997 else:
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002998 def test_memoryview_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002999 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04003000 :py:obj:`Connection.recv_into` can be passed a ``memoryview``
3001 instance and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01003002 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003003 self._no_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003004
3005
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003006 def test_memoryview_respects_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01003007 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003008 When called with a ``memoryview`` instance,
3009 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter
3010 and doesn't copy more than that number of bytes in.
Cory Benfield62d10332014-06-15 10:03:41 +01003011 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003012 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003013
3014
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003015 def test_memoryview_doesnt_overfill(self):
Cory Benfield62d10332014-06-15 10:03:41 +01003016 """
Jean-Paul Calderone8fd82552015-03-15 17:21:07 -04003017 When called with a ``memoryview`` instance,
3018 :py:obj:`Connection.recv_into` respects the size of the array and
3019 doesn't write more bytes into it than will fit.
Cory Benfield62d10332014-06-15 10:03:41 +01003020 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003021 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003022
3023
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003024 def test_memoryview_really_doesnt_overfill(self):
3025 """
3026 When called with a ``memoryview`` instance and an ``nbytes`` value
3027 that is too large, :py:obj:`Connection.recv_into` respects the size
3028 of the array and not the ``nbytes`` value and doesn't write more
3029 bytes into the buffer than will fit.
3030 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003031 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003032
3033
Cory Benfield62d10332014-06-15 10:03:41 +01003034
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003035class ConnectionSendallTests(TestCase, _LoopbackMixin):
3036 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003037 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003038 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003039 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003040 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003041 When called with arguments other than a string argument for its first
3042 parameter or with more than two arguments, :py:obj:`Connection.sendall`
3043 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003044 """
3045 connection = Connection(Context(TLSv1_METHOD), None)
3046 self.assertRaises(TypeError, connection.sendall)
3047 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003048 self.assertRaises(
3049 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003050
3051
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003052 def test_short(self):
3053 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003054 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003055 it.
3056 """
3057 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04003058 server.sendall(b('x'))
3059 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003060
3061
Abraham Martinef063482015-03-25 14:06:24 +00003062 def test_text(self):
3063 """
Jean-Paul Calderone93477422015-04-13 20:38:57 -04003064 :py:obj:`Connection.sendall` transmits all the content in the string
3065 passed to it raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003066 """
3067 server, client = self._loopback()
3068 with catch_warnings(record=True) as w:
3069 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003070 server.sendall(b"x".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003071 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003072 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003073 WARNING_TYPE_EXPECTED
3074 ),
3075 str(w[-1].message)
3076 )
3077 self.assertIs(w[-1].category, DeprecationWarning)
3078 self.assertEquals(client.recv(1), b"x")
Abraham Martinef063482015-03-25 14:06:24 +00003079
3080
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003081 try:
3082 memoryview
3083 except NameError:
3084 "cannot test sending memoryview without memoryview"
3085 else:
3086 def test_short_memoryview(self):
3087 """
3088 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003089 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003090 """
3091 server, client = self._loopback()
3092 server.sendall(memoryview(b('x')))
3093 self.assertEquals(client.recv(1), b('x'))
3094
3095
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003096 try:
3097 buffer
3098 except NameError:
3099 "cannot test sending buffers without buffers"
3100 else:
3101 def test_short_buffers(self):
3102 """
3103 When passed a buffer containing a small number of bytes,
3104 :py:obj:`Connection.sendall` transmits all of them.
3105 """
3106 server, client = self._loopback()
3107 server.sendall(buffer(b('x')))
3108 self.assertEquals(client.recv(1), b('x'))
3109
3110
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003111 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003112 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003113 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003114 it even if this requires multiple calls of an underlying write function.
3115 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003116 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003117 # Should be enough, underlying SSL_write should only do 16k at a time.
3118 # On Windows, after 32k of bytes the write will block (forever - because
3119 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04003120 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003121 server.sendall(message)
3122 accum = []
3123 received = 0
3124 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003125 data = client.recv(1024)
3126 accum.append(data)
3127 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04003128 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003129
3130
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003131 def test_closed(self):
3132 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003133 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003134 write error from the low level write call.
3135 """
3136 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003137 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003138 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003139 if platform == "win32":
3140 self.assertEqual(exc.args[0], ESHUTDOWN)
3141 else:
3142 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003143
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003144
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04003145
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003146class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
3147 """
3148 Tests for SSL renegotiation APIs.
3149 """
3150 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003151 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003152 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003153 arguments.
3154 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003155 connection = Connection(Context(TLSv1_METHOD), None)
3156 self.assertRaises(TypeError, connection.renegotiate, None)
3157
3158
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003159 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003160 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003161 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003162 any arguments.
3163 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003164 connection = Connection(Context(TLSv1_METHOD), None)
3165 self.assertRaises(TypeError, connection.total_renegotiations, None)
3166
3167
3168 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003169 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003170 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003171 renegotiations have happened.
3172 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003173 connection = Connection(Context(TLSv1_METHOD), None)
3174 self.assertEquals(connection.total_renegotiations(), 0)
3175
3176
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003177# def test_renegotiate(self):
3178# """
3179# """
3180# server, client = self._loopback()
3181
3182# server.send("hello world")
3183# self.assertEquals(client.recv(len("hello world")), "hello world")
3184
3185# self.assertEquals(server.total_renegotiations(), 0)
3186# self.assertTrue(server.renegotiate())
3187
3188# server.setblocking(False)
3189# client.setblocking(False)
3190# while server.renegotiate_pending():
3191# client.do_handshake()
3192# server.do_handshake()
3193
3194# self.assertEquals(server.total_renegotiations(), 1)
3195
3196
3197
3198
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003199class ErrorTests(TestCase):
3200 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003201 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003202 """
3203 def test_type(self):
3204 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003205 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003206 """
3207 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05003208 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05003209
3210
3211
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003212class ConstantsTests(TestCase):
3213 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003214 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003215
3216 These are values defined by OpenSSL intended only to be used as flags to
3217 OpenSSL APIs. The only assertions it seems can be made about them is
3218 their values.
3219 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003220 # unittest.TestCase has no skip mechanism
3221 if OP_NO_QUERY_MTU is not None:
3222 def test_op_no_query_mtu(self):
3223 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003224 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003225 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003226 """
3227 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
3228 else:
3229 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003230
3231
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003232 if OP_COOKIE_EXCHANGE is not None:
3233 def test_op_cookie_exchange(self):
3234 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003235 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003236 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003237 """
3238 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
3239 else:
3240 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003241
3242
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003243 if OP_NO_TICKET is not None:
3244 def test_op_no_ticket(self):
3245 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003246 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003247 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003248 """
3249 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04003250 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003251 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05003252
3253
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003254 if OP_NO_COMPRESSION is not None:
3255 def test_op_no_compression(self):
3256 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003257 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
3258 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003259 """
3260 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
3261 else:
3262 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3263
3264
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003265 def test_sess_cache_off(self):
3266 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003267 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3268 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003269 """
3270 self.assertEqual(0x0, SESS_CACHE_OFF)
3271
3272
3273 def test_sess_cache_client(self):
3274 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003275 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3276 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003277 """
3278 self.assertEqual(0x1, SESS_CACHE_CLIENT)
3279
3280
3281 def test_sess_cache_server(self):
3282 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003283 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3284 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003285 """
3286 self.assertEqual(0x2, SESS_CACHE_SERVER)
3287
3288
3289 def test_sess_cache_both(self):
3290 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003291 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3292 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003293 """
3294 self.assertEqual(0x3, SESS_CACHE_BOTH)
3295
3296
3297 def test_sess_cache_no_auto_clear(self):
3298 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003299 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3300 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3301 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003302 """
3303 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
3304
3305
3306 def test_sess_cache_no_internal_lookup(self):
3307 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003308 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3309 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3310 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003311 """
3312 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
3313
3314
3315 def test_sess_cache_no_internal_store(self):
3316 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003317 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3318 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3319 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003320 """
3321 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
3322
3323
3324 def test_sess_cache_no_internal(self):
3325 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003326 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3327 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
3328 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003329 """
3330 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
3331
3332
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04003333
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003334class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05003335 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003336 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003337 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003338 def _server(self, sock):
3339 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003340 Create a new server-side SSL :py:obj:`Connection` object wrapped around
3341 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003342 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003343 # Create the server side Connection. This is mostly setup boilerplate
3344 # - use TLSv1, use a particular certificate, etc.
3345 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003346 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
3347 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 -04003348 server_store = server_ctx.get_cert_store()
3349 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3350 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3351 server_ctx.check_privatekey()
3352 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003353 # Here the Connection is actually created. If None is passed as the 2nd
3354 # parameter, it indicates a memory BIO should be created.
3355 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003356 server_conn.set_accept_state()
3357 return server_conn
3358
3359
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003360 def _client(self, sock):
3361 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003362 Create a new client-side SSL :py:obj:`Connection` object wrapped around
3363 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003364 """
3365 # Now create the client side Connection. Similar boilerplate to the
3366 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003367 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003368 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
3369 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 -04003370 client_store = client_ctx.get_cert_store()
3371 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
3372 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
3373 client_ctx.check_privatekey()
3374 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003375 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003376 client_conn.set_connect_state()
3377 return client_conn
3378
3379
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003380 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003381 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003382 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003383 reading from the output of each and writing those bytes to the input of
3384 the other and in this way establish a connection and exchange
3385 application-level bytes with each other.
3386 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003387 server_conn = self._server(None)
3388 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003389
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003390 # There should be no key or nonces yet.
3391 self.assertIdentical(server_conn.master_key(), None)
3392 self.assertIdentical(server_conn.client_random(), None)
3393 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003394
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003395 # First, the handshake needs to happen. We'll deliver bytes back and
3396 # forth between the client and server until neither of them feels like
3397 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003398 self.assertIdentical(
3399 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003400
3401 # Now that the handshake is done, there should be a key and nonces.
3402 self.assertNotIdentical(server_conn.master_key(), None)
3403 self.assertNotIdentical(server_conn.client_random(), None)
3404 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04003405 self.assertEquals(server_conn.client_random(), client_conn.client_random())
3406 self.assertEquals(server_conn.server_random(), client_conn.server_random())
3407 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
3408 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003409
3410 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003411 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05003412
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003413 server_conn.write(important_message)
3414 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003415 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003416 (client_conn, important_message))
3417
3418 client_conn.write(important_message[::-1])
3419 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003420 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003421 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003422
3423
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003424 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003425 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003426 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003427
3428 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09003429 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003430 this test fails, there must be a problem outside the memory BIO
3431 code, as no memory BIO is involved here). Even though this isn't a
3432 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003433 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04003434 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003435
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003436 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05003437 client_conn.send(important_message)
3438 msg = server_conn.recv(1024)
3439 self.assertEqual(msg, important_message)
3440
3441 # Again in the other direction, just for fun.
3442 important_message = important_message[::-1]
3443 server_conn.send(important_message)
3444 msg = client_conn.recv(1024)
3445 self.assertEqual(msg, important_message)
3446
3447
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04003448 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003449 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003450 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
3451 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003452 """
3453 context = Context(SSLv3_METHOD)
3454 client = socket()
3455 clientSSL = Connection(context, client)
Alex Gaynor43307782015-09-04 09:05:45 -04003456 self.assertRaises(TypeError, clientSSL.bio_read, 100)
3457 self.assertRaises(TypeError, clientSSL.bio_write, "foo")
Alex Gaynor7e8b61e2015-09-04 13:13:05 -04003458 self.assertRaises(TypeError, clientSSL.bio_shutdown)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003459
3460
3461 def test_outgoingOverflow(self):
3462 """
3463 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09003464 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003465 returned and that many bytes from the beginning of the input can be
3466 read from the other end of the connection.
3467 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003468 server = self._server(None)
3469 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003470
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003471 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003472
3473 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003474 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003475 # Sanity check. We're trying to test what happens when the entire
3476 # input can't be sent. If the entire input was sent, this test is
3477 # meaningless.
3478 self.assertTrue(sent < size)
3479
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003480 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003481 self.assertIdentical(receiver, server)
3482
3483 # We can rely on all of these bytes being received at once because
3484 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
3485 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003486
3487
3488 def test_shutdown(self):
3489 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003490 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
3491 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003492 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003493 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003494 server.bio_shutdown()
3495 e = self.assertRaises(Error, server.recv, 1024)
3496 # We don't want WantReadError or ZeroReturnError or anything - it's a
3497 # handshake failure.
3498 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003499
3500
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003501 def test_unexpectedEndOfFile(self):
3502 """
3503 If the connection is lost before an orderly SSL shutdown occurs,
3504 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
3505 "Unexpected EOF".
3506 """
3507 server_conn, client_conn = self._loopback()
3508 client_conn.sock_shutdown(SHUT_RDWR)
3509 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
3510 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
3511
3512
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003513 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003514 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003515 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 -04003516
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003517 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003518 before the client and server are connected to each other. This
3519 function should specify a list of CAs for the server to send to the
3520 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09003521 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003522 times.
3523 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003524 server = self._server(None)
3525 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003526 self.assertEqual(client.get_client_ca_list(), [])
3527 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003528 ctx = server.get_context()
3529 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003530 self.assertEqual(client.get_client_ca_list(), [])
3531 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003532 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003533 self.assertEqual(client.get_client_ca_list(), expected)
3534 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003535
3536
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003537 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003538 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003539 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003540 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003541 """
3542 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003543 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
3544 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
3545 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003546
3547
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003548 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003549 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003550 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003551 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09003552 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003553 after the connection is set up.
3554 """
3555 def no_ca(ctx):
3556 ctx.set_client_ca_list([])
3557 return []
3558 self._check_client_ca_list(no_ca)
3559
3560
3561 def test_set_one_ca_list(self):
3562 """
3563 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003564 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003565 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003566 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003567 X509Name after the connection is set up.
3568 """
3569 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3570 cadesc = cacert.get_subject()
3571 def single_ca(ctx):
3572 ctx.set_client_ca_list([cadesc])
3573 return [cadesc]
3574 self._check_client_ca_list(single_ca)
3575
3576
3577 def test_set_multiple_ca_list(self):
3578 """
3579 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003580 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003581 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003582 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003583 X509Names after the connection is set up.
3584 """
3585 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3586 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3587
3588 sedesc = secert.get_subject()
3589 cldesc = clcert.get_subject()
3590
3591 def multiple_ca(ctx):
3592 L = [sedesc, cldesc]
3593 ctx.set_client_ca_list(L)
3594 return L
3595 self._check_client_ca_list(multiple_ca)
3596
3597
3598 def test_reset_ca_list(self):
3599 """
3600 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09003601 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003602 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003603 """
3604 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3605 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3606 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3607
3608 cadesc = cacert.get_subject()
3609 sedesc = secert.get_subject()
3610 cldesc = clcert.get_subject()
3611
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003612 def changed_ca(ctx):
3613 ctx.set_client_ca_list([sedesc, cldesc])
3614 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003615 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003616 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003617
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003618
3619 def test_mutated_ca_list(self):
3620 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003621 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003622 afterwards, this does not affect the list of CA names sent to the
3623 client.
3624 """
3625 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3626 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3627
3628 cadesc = cacert.get_subject()
3629 sedesc = secert.get_subject()
3630
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003631 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003632 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003633 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003634 L.append(sedesc)
3635 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003636 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003637
3638
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003639 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003640 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003641 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003642 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003643 """
3644 ctx = Context(TLSv1_METHOD)
3645 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003646 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003647 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003648 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003649
3650
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003651 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003652 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003653 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09003654 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003655 """
3656 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3657 cadesc = cacert.get_subject()
3658 def single_ca(ctx):
3659 ctx.add_client_ca(cacert)
3660 return [cadesc]
3661 self._check_client_ca_list(single_ca)
3662
3663
3664 def test_multiple_add_client_ca(self):
3665 """
3666 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09003667 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003668 """
3669 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3670 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3671
3672 cadesc = cacert.get_subject()
3673 sedesc = secert.get_subject()
3674
3675 def multiple_ca(ctx):
3676 ctx.add_client_ca(cacert)
3677 ctx.add_client_ca(secert)
3678 return [cadesc, sedesc]
3679 self._check_client_ca_list(multiple_ca)
3680
3681
3682 def test_set_and_add_client_ca(self):
3683 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003684 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
3685 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003686 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003687 """
3688 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3689 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3690 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3691
3692 cadesc = cacert.get_subject()
3693 sedesc = secert.get_subject()
3694 cldesc = clcert.get_subject()
3695
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003696 def mixed_set_add_ca(ctx):
3697 ctx.set_client_ca_list([cadesc, sedesc])
3698 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003699 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003700 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003701
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003702
3703 def test_set_after_add_client_ca(self):
3704 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003705 A call to :py:obj:`Context.set_client_ca_list` after a call to
3706 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003707 call with the names specified by the latter cal.
3708 """
3709 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3710 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3711 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3712
3713 cadesc = cacert.get_subject()
3714 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003715
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003716 def set_replaces_add_ca(ctx):
3717 ctx.add_client_ca(clcert)
3718 ctx.set_client_ca_list([cadesc])
3719 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003720 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003721 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003722
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003723
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003724
3725class ConnectionBIOTests(TestCase):
3726 """
3727 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3728 """
3729 def test_wantReadError(self):
3730 """
3731 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
3732 if there are no bytes available to be read from the BIO.
3733 """
3734 ctx = Context(TLSv1_METHOD)
3735 conn = Connection(ctx, None)
3736 self.assertRaises(WantReadError, conn.bio_read, 1024)
3737
3738
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003739 def test_buffer_size(self):
3740 """
3741 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3742 number of bytes to read and return.
3743 """
3744 ctx = Context(TLSv1_METHOD)
3745 conn = Connection(ctx, None)
3746 conn.set_connect_state()
3747 try:
3748 conn.do_handshake()
3749 except WantReadError:
3750 pass
3751 data = conn.bio_read(2)
3752 self.assertEqual(2, len(data))
3753
3754
3755 if not PY3:
3756 def test_buffer_size_long(self):
3757 """
3758 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3759 :py:obj:`long` as well as :py:obj:`int`.
3760 """
3761 ctx = Context(TLSv1_METHOD)
3762 conn = Connection(ctx, None)
3763 conn.set_connect_state()
3764 try:
3765 conn.do_handshake()
3766 except WantReadError:
3767 pass
3768 data = conn.bio_read(long(2))
3769 self.assertEqual(2, len(data))
3770
3771
3772
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003773
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003774class InfoConstantTests(TestCase):
3775 """
3776 Tests for assorted constants exposed for use in info callbacks.
3777 """
3778 def test_integers(self):
3779 """
3780 All of the info constants are integers.
3781
3782 This is a very weak test. It would be nice to have one that actually
3783 verifies that as certain info events happen, the value passed to the
3784 info callback matches up with the constant exposed by OpenSSL.SSL.
3785 """
3786 for const in [
3787 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3788 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3789 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3790 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3791 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
3792 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
3793
3794 self.assertTrue(isinstance(const, int))
3795
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003796
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003797if __name__ == '__main__':
3798 main()