blob: 6c2019b3bbe5b04c82512dd13c50968442836535 [file] [log] [blame]
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05001# Copyright (C) Jean-Paul Calderone
2# See LICENSE for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04003
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04004"""
Jonathan Ballet648875f2011-07-16 14:14:58 +09005Unit tests for :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04006"""
7
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05008from gc import collect, get_referrers
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02009from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE, ESHUTDOWN
Jean-Paul Calderone516c12c2015-04-13 20:34:57 -040010from sys import platform, getfilesystemencoding
Maximilian Hils1d95dea2015-08-17 19:27:20 +020011from socket import MSG_PEEK, SHUT_RDWR, error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040012from os import makedirs
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040013from os.path import join
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -040014from unittest import main
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040015from weakref import ref
Abraham Martinef063482015-03-25 14:06:24 +000016from warnings import catch_warnings, simplefilter
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050017
Hynek Schlawack734d3022015-09-05 19:19:32 +020018import pytest
19
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -040020from six import PY3, text_type, u
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050021
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040022from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080023from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040024from OpenSSL.crypto import dump_privatekey, load_privatekey
25from OpenSSL.crypto import dump_certificate, load_certificate
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040026from OpenSSL.crypto import get_elliptic_curves
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040027
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040028from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
29from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040030from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040031from OpenSSL.SSL import (
32 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
33 TLSv1_1_METHOD, TLSv1_2_METHOD)
34from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040035from OpenSSL.SSL import (
36 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040037
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040038from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050039 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
40 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
41 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
42
43from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070044 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050045from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070046 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040047
Cory Benfieldba1820d2015-04-13 17:39:12 -040048from OpenSSL._util import lib as _lib
49
Jean-Paul Calderone17eca482015-04-13 20:31:07 -040050from OpenSSL.test.util import WARNING_TYPE_EXPECTED, NON_ASCII, TestCase, b
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040051from OpenSSL.test.test_crypto import (
Jean-Paul Calderoneda6399a2015-04-13 20:52:29 -040052 cleartextCertificatePEM, cleartextPrivateKeyPEM,
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040053 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
54 root_cert_pem)
55
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050056try:
57 from OpenSSL.SSL import OP_NO_QUERY_MTU
58except ImportError:
59 OP_NO_QUERY_MTU = None
60try:
61 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
62except ImportError:
63 OP_COOKIE_EXCHANGE = None
64try:
65 from OpenSSL.SSL import OP_NO_TICKET
66except ImportError:
67 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040068
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040069try:
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -040070 from OpenSSL.SSL import OP_NO_COMPRESSION
71except ImportError:
72 OP_NO_COMPRESSION = None
73
74try:
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040075 from OpenSSL.SSL import MODE_RELEASE_BUFFERS
76except ImportError:
77 MODE_RELEASE_BUFFERS = None
78
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040079try:
80 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
81except ImportError:
82 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
83
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040084from OpenSSL.SSL import (
85 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
86 SSL_ST_OK, SSL_ST_RENEGOTIATE,
87 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
88 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
89 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
90 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040091
Hynek Schlawackde00dd52015-09-05 19:09:26 +020092
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040093# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
94# to use)
95dhparam = """\
96-----BEGIN DH PARAMETERS-----
97MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
98-----END DH PARAMETERS-----
99"""
100
101
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400102def join_bytes_or_unicode(prefix, suffix):
103 """
104 Join two path components of either ``bytes`` or ``unicode``.
105
106 The return type is the same as the type of ``prefix``.
107 """
108 # If the types are the same, nothing special is necessary.
109 if type(prefix) == type(suffix):
110 return join(prefix, suffix)
111
112 # Otherwise, coerce suffix to the type of prefix.
113 if isinstance(prefix, text_type):
114 return join(prefix, suffix.decode(getfilesystemencoding()))
115 else:
116 return join(prefix, suffix.encode(getfilesystemencoding()))
117
118
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400119def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400120 return ok
121
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400122
Rick Deanb1ccd562009-07-09 23:52:39 -0500123def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400124 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400125 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400126 """
127 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500128 port = socket()
129 port.bind(('', 0))
130 port.listen(1)
131 client = socket()
132 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400133 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400134 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500135 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500136
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400137 # Let's pass some unencrypted data to make sure our socket connection is
138 # fine. Just one byte, so we don't have to worry about buffers getting
139 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400140 server.send(b("x"))
141 assert client.recv(1024) == b("x")
142 client.send(b("y"))
143 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500144
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400145 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400146 server.setblocking(False)
147 client.setblocking(False)
Jim Shaver46f28912015-05-29 19:32:16 -0400148
Rick Deanb1ccd562009-07-09 23:52:39 -0500149 return (server, client)
150
151
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400152def handshake(client, server):
153 conns = [client, server]
154 while conns:
155 for conn in conns:
156 try:
157 conn.do_handshake()
158 except WantReadError:
159 pass
160 else:
161 conns.remove(conn)
162
163
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400164def _create_certificate_chain():
165 """
166 Construct and return a chain of certificates.
167
168 1. A new self-signed certificate authority certificate (cacert)
169 2. A new intermediate certificate signed by cacert (icert)
170 3. A new server certificate signed by icert (scert)
171 """
172 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
173
174 # Step 1
175 cakey = PKey()
176 cakey.generate_key(TYPE_RSA, 512)
177 cacert = X509()
178 cacert.get_subject().commonName = "Authority Certificate"
179 cacert.set_issuer(cacert.get_subject())
180 cacert.set_pubkey(cakey)
181 cacert.set_notBefore(b("20000101000000Z"))
182 cacert.set_notAfter(b("20200101000000Z"))
183 cacert.add_extensions([caext])
184 cacert.set_serial_number(0)
185 cacert.sign(cakey, "sha1")
186
187 # Step 2
188 ikey = PKey()
189 ikey.generate_key(TYPE_RSA, 512)
190 icert = X509()
191 icert.get_subject().commonName = "Intermediate Certificate"
192 icert.set_issuer(cacert.get_subject())
193 icert.set_pubkey(ikey)
194 icert.set_notBefore(b("20000101000000Z"))
195 icert.set_notAfter(b("20200101000000Z"))
196 icert.add_extensions([caext])
197 icert.set_serial_number(0)
198 icert.sign(cakey, "sha1")
199
200 # Step 3
201 skey = PKey()
202 skey.generate_key(TYPE_RSA, 512)
203 scert = X509()
204 scert.get_subject().commonName = "Server Certificate"
205 scert.set_issuer(icert.get_subject())
206 scert.set_pubkey(skey)
207 scert.set_notBefore(b("20000101000000Z"))
208 scert.set_notAfter(b("20200101000000Z"))
209 scert.add_extensions([
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200210 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400211 scert.set_serial_number(0)
212 scert.sign(ikey, "sha1")
213
214 return [(cakey, cacert), (ikey, icert), (skey, scert)]
215
216
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400217class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400218 """
219 Helper mixin which defines methods for creating a connected socket pair and
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200220 for forcing two connected SSL sockets to talk to each other via memory
221 BIOs.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400222 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500223 def _loopbackClientFactory(self, socket):
224 client = Connection(Context(TLSv1_METHOD), socket)
225 client.set_connect_state()
226 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400227
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500228 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400229 ctx = Context(TLSv1_METHOD)
230 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
231 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500232 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400233 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500234 return server
235
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500236 def _loopback(self, serverFactory=None, clientFactory=None):
237 if serverFactory is None:
238 serverFactory = self._loopbackServerFactory
239 if clientFactory is None:
240 clientFactory = self._loopbackClientFactory
241
242 (server, client) = socket_pair()
243 server = serverFactory(server)
244 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400245
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400246 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400247
248 server.setblocking(True)
249 client.setblocking(True)
250 return server, client
251
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400252 def _interactInMemory(self, client_conn, server_conn):
253 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900254 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400255 objects. Copy bytes back and forth between their send/receive buffers
256 for as long as there is anything to copy. When there is nothing more
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200257 to copy, return :py:obj:`None`. If one of them actually manages to
258 deliver some application bytes, return a two-tuple of the connection
259 from which the bytes were read and the bytes themselves.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400260 """
261 wrote = True
262 while wrote:
263 # Loop until neither side has anything to say
264 wrote = False
265
266 # Copy stuff from each side's send buffer to the other side's
267 # receive buffer.
268 for (read, write) in [(client_conn, server_conn),
269 (server_conn, client_conn)]:
270
271 # Give the side a chance to generate some more bytes, or
272 # succeed.
273 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400274 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400275 except WantReadError:
276 # It didn't succeed, so we'll hope it generated some
277 # output.
278 pass
279 else:
280 # It did succeed, so we'll stop now and let the caller deal
281 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400282 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400283
284 while True:
285 # Keep copying as long as there's more stuff there.
286 try:
287 dirty = read.bio_read(4096)
288 except WantReadError:
289 # Okay, nothing more waiting to be sent. Stop
290 # processing this send buffer.
291 break
292 else:
293 # Keep track of the fact that someone generated some
294 # output.
295 wrote = True
296 write.bio_write(dirty)
297
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400298 def _handshakeInMemory(self, client_conn, server_conn):
Jean-Paul Calderoneb2b40782014-05-06 08:47:40 -0400299 """
300 Perform the TLS handshake between two :py:class:`Connection` instances
301 connected to each other via memory BIOs.
302 """
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400303 client_conn.set_connect_state()
304 server_conn.set_accept_state()
305
306 for conn in [client_conn, server_conn]:
307 try:
308 conn.do_handshake()
309 except WantReadError:
310 pass
311
312 self._interactInMemory(client_conn, server_conn)
313
314
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400315class VersionTests(TestCase):
316 """
317 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900318 :py:obj:`OpenSSL.SSL.SSLeay_version` and
319 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400320 """
321 def test_OPENSSL_VERSION_NUMBER(self):
322 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900323 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400324 byte and the patch, fix, minor, and major versions in the
325 nibbles above that.
326 """
327 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
328
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400329 def test_SSLeay_version(self):
330 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900331 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400332 one of a number of version strings based on that indicator.
333 """
334 versions = {}
335 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
336 SSLEAY_PLATFORM, SSLEAY_DIR]:
337 version = SSLeay_version(t)
338 versions[version] = t
339 self.assertTrue(isinstance(version, bytes))
340 self.assertEqual(len(versions), 5)
341
342
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400343class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400344 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900345 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400346 """
347 def test_method(self):
348 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200349 :py:obj:`Context` can be instantiated with one of
350 :py:obj:`SSLv2_METHOD`, :py:obj:`SSLv3_METHOD`,
351 :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400352 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400353 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400354 methods = [
355 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
356 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400357 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400358
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400359 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
360 for meth in maybe:
361 try:
362 Context(meth)
363 except (Error, ValueError):
364 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
365 # don't. Difficult to say in advance.
366 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400367
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400368 self.assertRaises(TypeError, Context, "")
369 self.assertRaises(ValueError, Context, 10)
370
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500371 if not PY3:
372 def test_method_long(self):
373 """
374 On Python 2 :py:class:`Context` accepts values of type
375 :py:obj:`long` as well as :py:obj:`int`.
376 """
377 Context(long(TLSv1_METHOD))
378
Rick Deane15b1472009-07-09 15:53:42 -0500379 def test_type(self):
380 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200381 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type
382 object and can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500383 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400384 self.assertIdentical(Context, ContextType)
385 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500386
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400387 def test_use_privatekey(self):
388 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200389 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey`
390 instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400391 """
392 key = PKey()
393 key.generate_key(TYPE_RSA, 128)
394 ctx = Context(TLSv1_METHOD)
395 ctx.use_privatekey(key)
396 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400397
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800398 def test_use_privatekey_file_missing(self):
399 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200400 :py:obj:`Context.use_privatekey_file` raises
401 :py:obj:`OpenSSL.SSL.Error` when passed the name of a file which does
402 not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800403 """
404 ctx = Context(TLSv1_METHOD)
405 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
406
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400407 def _use_privatekey_file_test(self, pemfile, filetype):
408 """
409 Verify that calling ``Context.use_privatekey_file`` with the given
410 arguments does not raise an exception.
411 """
412 key = PKey()
413 key.generate_key(TYPE_RSA, 128)
414
415 with open(pemfile, "wt") as pem:
416 pem.write(
417 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
418 )
419
420 ctx = Context(TLSv1_METHOD)
421 ctx.use_privatekey_file(pemfile, filetype)
422
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400423 def test_use_privatekey_file_bytes(self):
424 """
425 A private key can be specified from a file by passing a ``bytes``
426 instance giving the file name to ``Context.use_privatekey_file``.
427 """
428 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400429 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400430 FILETYPE_PEM,
431 )
432
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400433 def test_use_privatekey_file_unicode(self):
434 """
435 A private key can be specified from a file by passing a ``unicode``
436 instance giving the file name to ``Context.use_privatekey_file``.
437 """
438 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400439 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400440 FILETYPE_PEM,
441 )
442
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500443 if not PY3:
444 def test_use_privatekey_file_long(self):
445 """
446 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
447 filetype of type :py:obj:`long` as well as :py:obj:`int`.
448 """
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400449 self._use_privatekey_file_test(self.mktemp(), long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500450
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800451 def test_use_certificate_wrong_args(self):
452 """
453 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200454 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as
455 an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800456 """
457 ctx = Context(TLSv1_METHOD)
458 self.assertRaises(TypeError, ctx.use_certificate)
459 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200460 self.assertRaises(
461 TypeError, ctx.use_certificate, X509(), "hello, world"
462 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800463
464 def test_use_certificate_uninitialized(self):
465 """
466 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
467 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
468 initialized (ie, which does not actually have any certificate data).
469 """
470 ctx = Context(TLSv1_METHOD)
471 self.assertRaises(Error, ctx.use_certificate, X509())
472
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800473 def test_use_certificate(self):
474 """
475 :py:obj:`Context.use_certificate` sets the certificate which will be
476 used to identify connections created using the context.
477 """
478 # TODO
479 # Hard to assert anything. But we could set a privatekey then ask
480 # OpenSSL if the cert and key agree using check_privatekey. Then as
481 # long as check_privatekey works right we're good...
482 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200483 ctx.use_certificate(
484 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
485 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800486
487 def test_use_certificate_file_wrong_args(self):
488 """
489 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
490 called with zero arguments or more than two arguments, or if the first
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200491 argument is not a byte string or the second argumnent is not an
492 integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800493 """
494 ctx = Context(TLSv1_METHOD)
495 self.assertRaises(TypeError, ctx.use_certificate_file)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200496 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile",
497 object())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800498 self.assertRaises(
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200499 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM,
500 object())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800501 self.assertRaises(
502 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
503 self.assertRaises(
504 TypeError, ctx.use_certificate_file, b"somefile", object())
505
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800506 def test_use_certificate_file_missing(self):
507 """
508 :py:obj:`Context.use_certificate_file` raises
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200509 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does
510 not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800511 """
512 ctx = Context(TLSv1_METHOD)
513 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
514
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400515 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800516 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400517 Verify that calling ``Context.use_certificate_file`` with the given
518 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800519 """
520 # TODO
521 # Hard to assert anything. But we could set a privatekey then ask
522 # OpenSSL if the cert and key agree using check_privatekey. Then as
523 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400524 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800525 pem_file.write(cleartextCertificatePEM)
526
527 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400528 ctx.use_certificate_file(certificate_file)
529
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400530 def test_use_certificate_file_bytes(self):
531 """
532 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
533 ``bytes`` filename) which will be used to identify connections created
534 using the context.
535 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400536 filename = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400537 self._use_certificate_file_test(filename)
538
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400539 def test_use_certificate_file_unicode(self):
540 """
541 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
542 ``bytes`` filename) which will be used to identify connections created
543 using the context.
544 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400545 filename = self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400546 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800547
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500548 if not PY3:
549 def test_use_certificate_file_long(self):
550 """
551 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
552 filetype of type :py:obj:`long` as well as :py:obj:`int`.
553 """
554 pem_filename = self.mktemp()
555 with open(pem_filename, "wb") as pem_file:
556 pem_file.write(cleartextCertificatePEM)
557
558 ctx = Context(TLSv1_METHOD)
559 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
560
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500561 def test_check_privatekey_valid(self):
562 """
563 :py:obj:`Context.check_privatekey` returns :py:obj:`None` if the
564 :py:obj:`Context` instance has been configured to use a matched key and
565 certificate pair.
566 """
567 key = load_privatekey(FILETYPE_PEM, client_key_pem)
568 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
569 context = Context(TLSv1_METHOD)
570 context.use_privatekey(key)
571 context.use_certificate(cert)
572 self.assertIs(None, context.check_privatekey())
573
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500574 def test_check_privatekey_invalid(self):
575 """
576 :py:obj:`Context.check_privatekey` raises :py:obj:`Error` if the
577 :py:obj:`Context` instance has been configured to use a key and
578 certificate pair which don't relate to each other.
579 """
580 key = load_privatekey(FILETYPE_PEM, client_key_pem)
581 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
582 context = Context(TLSv1_METHOD)
583 context.use_privatekey(key)
584 context.use_certificate(cert)
585 self.assertRaises(Error, context.check_privatekey)
586
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500587 def test_check_privatekey_wrong_args(self):
588 """
589 :py:obj:`Context.check_privatekey` raises :py:obj:`TypeError` if called
590 with other than no arguments.
591 """
592 context = Context(TLSv1_METHOD)
593 self.assertRaises(TypeError, context.check_privatekey, object())
594
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400595 def test_set_app_data_wrong_args(self):
596 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200597 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called
598 with other than one argument.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400599 """
600 context = Context(TLSv1_METHOD)
601 self.assertRaises(TypeError, context.set_app_data)
602 self.assertRaises(TypeError, context.set_app_data, None, None)
603
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400604 def test_get_app_data_wrong_args(self):
605 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200606 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called
607 with any arguments.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400608 """
609 context = Context(TLSv1_METHOD)
610 self.assertRaises(TypeError, context.get_app_data, None)
611
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400612 def test_app_data(self):
613 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200614 :py:obj:`Context.set_app_data` stores an object for later retrieval
615 using :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400616 """
617 app_data = object()
618 context = Context(TLSv1_METHOD)
619 context.set_app_data(app_data)
620 self.assertIdentical(context.get_app_data(), app_data)
621
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400622 def test_set_options_wrong_args(self):
623 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200624 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with
625 the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400626 """
627 context = Context(TLSv1_METHOD)
628 self.assertRaises(TypeError, context.set_options)
629 self.assertRaises(TypeError, context.set_options, None)
630 self.assertRaises(TypeError, context.set_options, 1, None)
631
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500632 def test_set_options(self):
633 """
634 :py:obj:`Context.set_options` returns the new options value.
635 """
636 context = Context(TLSv1_METHOD)
637 options = context.set_options(OP_NO_SSLv2)
638 self.assertTrue(OP_NO_SSLv2 & options)
639
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500640 if not PY3:
641 def test_set_options_long(self):
642 """
643 On Python 2 :py:obj:`Context.set_options` accepts values of type
644 :py:obj:`long` as well as :py:obj:`int`.
645 """
646 context = Context(TLSv1_METHOD)
647 options = context.set_options(long(OP_NO_SSLv2))
648 self.assertTrue(OP_NO_SSLv2 & options)
649
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300650 def test_set_mode_wrong_args(self):
651 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200652 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with
653 the wrong number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300654 """
655 context = Context(TLSv1_METHOD)
656 self.assertRaises(TypeError, context.set_mode)
657 self.assertRaises(TypeError, context.set_mode, None)
658 self.assertRaises(TypeError, context.set_mode, 1, None)
659
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400660 if MODE_RELEASE_BUFFERS is not None:
661 def test_set_mode(self):
662 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200663 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the
664 newly set mode.
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400665 """
666 context = Context(TLSv1_METHOD)
667 self.assertTrue(
668 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500669
670 if not PY3:
671 def test_set_mode_long(self):
672 """
673 On Python 2 :py:obj:`Context.set_mode` accepts values of type
674 :py:obj:`long` as well as :py:obj:`int`.
675 """
676 context = Context(TLSv1_METHOD)
677 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
678 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400679 else:
680 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
681
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400682 def test_set_timeout_wrong_args(self):
683 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200684 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with
685 the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400686 """
687 context = Context(TLSv1_METHOD)
688 self.assertRaises(TypeError, context.set_timeout)
689 self.assertRaises(TypeError, context.set_timeout, None)
690 self.assertRaises(TypeError, context.set_timeout, 1, None)
691
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400692 def test_get_timeout_wrong_args(self):
693 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200694 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with
695 any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400696 """
697 context = Context(TLSv1_METHOD)
698 self.assertRaises(TypeError, context.get_timeout, None)
699
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400700 def test_timeout(self):
701 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200702 :py:obj:`Context.set_timeout` sets the session timeout for all
703 connections created using the context object.
704 :py:obj:`Context.get_timeout` retrieves this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400705 """
706 context = Context(TLSv1_METHOD)
707 context.set_timeout(1234)
708 self.assertEquals(context.get_timeout(), 1234)
709
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500710 if not PY3:
711 def test_timeout_long(self):
712 """
713 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
714 `long` as well as int.
715 """
716 context = Context(TLSv1_METHOD)
717 context.set_timeout(long(1234))
718 self.assertEquals(context.get_timeout(), 1234)
719
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400720 def test_set_verify_depth_wrong_args(self):
721 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200722 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called
723 with the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400724 """
725 context = Context(TLSv1_METHOD)
726 self.assertRaises(TypeError, context.set_verify_depth)
727 self.assertRaises(TypeError, context.set_verify_depth, None)
728 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
729
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400730 def test_get_verify_depth_wrong_args(self):
731 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200732 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called
733 with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400734 """
735 context = Context(TLSv1_METHOD)
736 self.assertRaises(TypeError, context.get_verify_depth, None)
737
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400738 def test_verify_depth(self):
739 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200740 :py:obj:`Context.set_verify_depth` sets the number of certificates in
741 a chain to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900742 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400743 """
744 context = Context(TLSv1_METHOD)
745 context.set_verify_depth(11)
746 self.assertEquals(context.get_verify_depth(), 11)
747
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500748 if not PY3:
749 def test_verify_depth_long(self):
750 """
751 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
752 type `long` as well as int.
753 """
754 context = Context(TLSv1_METHOD)
755 context.set_verify_depth(long(11))
756 self.assertEquals(context.get_verify_depth(), 11)
757
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400758 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400759 """
760 Write a new private key out to a new file, encrypted using the given
761 passphrase. Return the path to the new file.
762 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400763 key = PKey()
764 key.generate_key(TYPE_RSA, 128)
765 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400766 fObj = open(pemFile, 'w')
767 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
768 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400769 fObj.close()
770 return pemFile
771
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400772 def test_set_passwd_cb_wrong_args(self):
773 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200774 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called
775 with the wrong arguments or with a non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400776 """
777 context = Context(TLSv1_METHOD)
778 self.assertRaises(TypeError, context.set_passwd_cb)
779 self.assertRaises(TypeError, context.set_passwd_cb, None)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200780 self.assertRaises(
781 TypeError, context.set_passwd_cb, lambda: None, None, None
Hynek Schlawack2c013a92015-09-05 19:33:05 +0200782 ) # pragma: nocover
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400783
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400784 def test_set_passwd_cb(self):
785 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200786 :py:obj:`Context.set_passwd_cb` accepts a callable which will be
787 invoked when a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400788 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400789 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400790 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400791 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200792
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400793 def passphraseCallback(maxlen, verify, extra):
794 calledWith.append((maxlen, verify, extra))
795 return passphrase
796 context = Context(TLSv1_METHOD)
797 context.set_passwd_cb(passphraseCallback)
798 context.use_privatekey_file(pemFile)
799 self.assertTrue(len(calledWith), 1)
800 self.assertTrue(isinstance(calledWith[0][0], int))
801 self.assertTrue(isinstance(calledWith[0][1], int))
802 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400803
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400804 def test_passwd_callback_exception(self):
805 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200806 :py:obj:`Context.use_privatekey_file` propagates any exception raised
807 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400808 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400809 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200810
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400811 def passphraseCallback(maxlen, verify, extra):
812 raise RuntimeError("Sorry, I am a fail.")
813
814 context = Context(TLSv1_METHOD)
815 context.set_passwd_cb(passphraseCallback)
816 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
817
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400818 def test_passwd_callback_false(self):
819 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200820 :py:obj:`Context.use_privatekey_file` raises
821 :py:obj:`OpenSSL.SSL.Error` if the passphrase callback returns a false
822 value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400823 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400824 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200825
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400826 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500827 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400828
829 context = Context(TLSv1_METHOD)
830 context.set_passwd_cb(passphraseCallback)
831 self.assertRaises(Error, context.use_privatekey_file, pemFile)
832
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400833 def test_passwd_callback_non_string(self):
834 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200835 :py:obj:`Context.use_privatekey_file` raises
836 :py:obj:`OpenSSL.SSL.Error` if the passphrase callback returns a true
837 non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400838 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400839 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200840
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400841 def passphraseCallback(maxlen, verify, extra):
842 return 10
843
844 context = Context(TLSv1_METHOD)
845 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800846 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400847
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400848 def test_passwd_callback_too_long(self):
849 """
850 If the passphrase returned by the passphrase callback returns a string
851 longer than the indicated maximum length, it is truncated.
852 """
853 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400854 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400855 pemFile = self._write_encrypted_pem(passphrase)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200856
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400857 def passphraseCallback(maxlen, verify, extra):
858 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400859 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400860
861 context = Context(TLSv1_METHOD)
862 context.set_passwd_cb(passphraseCallback)
863 # This shall succeed because the truncated result is the correct
864 # passphrase.
865 context.use_privatekey_file(pemFile)
866
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400867 def test_set_info_callback(self):
868 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200869 :py:obj:`Context.set_info_callback` accepts a callable which will be
870 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400871 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500872 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400873
874 clientSSL = Connection(Context(TLSv1_METHOD), client)
875 clientSSL.set_connect_state()
876
877 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200878
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400879 def info(conn, where, ret):
880 called.append((conn, where, ret))
881 context = Context(TLSv1_METHOD)
882 context.set_info_callback(info)
883 context.use_certificate(
884 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
885 context.use_privatekey(
886 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
887
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400888 serverSSL = Connection(context, server)
889 serverSSL.set_accept_state()
890
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500891 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400892
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500893 # The callback must always be called with a Connection instance as the
894 # first argument. It would probably be better to split this into
895 # separate tests for client and server side info callbacks so we could
896 # assert it is called with the right Connection instance. It would
897 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500898 notConnections = [
899 conn for (conn, where, ret) in called
900 if not isinstance(conn, Connection)]
901 self.assertEqual(
902 [], notConnections,
903 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400904
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400905 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400906 """
907 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400908 its :py:obj:`load_verify_locations` method with the given arguments.
909 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400910 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500911 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400912
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400913 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400914 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400915 # Require that the server certificate verify properly or the
916 # connection will fail.
917 clientContext.set_verify(
918 VERIFY_PEER,
919 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
920
921 clientSSL = Connection(clientContext, client)
922 clientSSL.set_connect_state()
923
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400924 serverContext = Context(TLSv1_METHOD)
925 serverContext.use_certificate(
926 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
927 serverContext.use_privatekey(
928 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
929
930 serverSSL = Connection(serverContext, server)
931 serverSSL.set_accept_state()
932
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400933 # Without load_verify_locations above, the handshake
934 # will fail:
935 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
936 # 'certificate verify failed')]
937 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400938
939 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400940 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400941
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400942 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400943 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400944 Verify that if path to a file containing a certificate is passed to
945 ``Context.load_verify_locations`` for the ``cafile`` parameter, that
946 certificate is used as a trust root for the purposes of verifying
947 connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400948 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400949 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400950 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400951 fObj.close()
952
953 self._load_verify_locations_test(cafile)
954
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400955 def test_load_verify_bytes_cafile(self):
956 """
957 :py:obj:`Context.load_verify_locations` accepts a file name as a
958 ``bytes`` instance and uses the certificates within for verification
959 purposes.
960 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400961 cafile = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400962 self._load_verify_cafile(cafile)
963
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400964 def test_load_verify_unicode_cafile(self):
965 """
966 :py:obj:`Context.load_verify_locations` accepts a file name as a
967 ``unicode`` instance and uses the certificates within for verification
968 purposes.
969 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -0400970 self._load_verify_cafile(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400971 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -0400972 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400973
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400974 def test_load_verify_invalid_file(self):
975 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200976 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when
977 passed a non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400978 """
979 clientContext = Context(TLSv1_METHOD)
980 self.assertRaises(
981 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400982
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400983 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400984 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400985 Verify that if path to a directory containing certificate files is
986 passed to ``Context.load_verify_locations`` for the ``capath``
987 parameter, those certificates are used as trust roots for the purposes
988 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400989 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400990 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400991 # Hash values computed manually with c_rehash to avoid depending on
992 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
993 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500994 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400995 cafile = join_bytes_or_unicode(capath, name)
996 with open(cafile, 'w') as fObj:
997 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400998
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400999 self._load_verify_locations_test(None, capath)
1000
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001001 def test_load_verify_directory_bytes_capath(self):
1002 """
1003 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1004 ``bytes`` instance and uses the certificates within for verification
1005 purposes.
1006 """
1007 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001008 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001009 )
1010
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001011 def test_load_verify_directory_unicode_capath(self):
1012 """
1013 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1014 ``unicode`` instance and uses the certificates within for verification
1015 purposes.
1016 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001017 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001018 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001019 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001020
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001021 def test_load_verify_locations_wrong_args(self):
1022 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001023 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if
1024 called with the wrong number of arguments or with non-:py:obj:`str`
1025 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001026 """
1027 context = Context(TLSv1_METHOD)
1028 self.assertRaises(TypeError, context.load_verify_locations)
1029 self.assertRaises(TypeError, context.load_verify_locations, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001030 self.assertRaises(
1031 TypeError, context.load_verify_locations, object(), object()
1032 )
1033 self.assertRaises(
1034 TypeError, context.load_verify_locations, None, None, None
1035 )
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001036
Hynek Schlawack734d3022015-09-05 19:19:32 +02001037 @pytest.mark.skipif(
1038 platform == "win32",
1039 reason="set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001040 "See LP#404343 and LP#404344."
Hynek Schlawack734d3022015-09-05 19:19:32 +02001041 )
1042 def test_set_default_verify_paths(self):
1043 """
1044 :py:obj:`Context.set_default_verify_paths` causes the
1045 platform-specific CA certificate locations to be used for
1046 verification purposes.
1047 """
1048 # Testing this requires a server with a certificate signed by one
1049 # of the CAs in the platform CA location. Getting one of those
1050 # costs money. Fortunately (or unfortunately, depending on your
1051 # perspective), it's easy to think of a public server on the
1052 # internet which has such a certificate. Connecting to the network
1053 # in a unit test is bad, but it's the only way I can think of to
1054 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001055
Hynek Schlawack734d3022015-09-05 19:19:32 +02001056 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
1057 context = Context(TLSv1_METHOD)
1058 context.set_default_verify_paths()
1059 context.set_verify(
1060 VERIFY_PEER,
1061 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001062
Hynek Schlawack734d3022015-09-05 19:19:32 +02001063 client = socket()
1064 client.connect(('verisign.com', 443))
1065 clientSSL = Connection(context, client)
1066 clientSSL.set_connect_state()
1067 clientSSL.do_handshake()
1068 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
1069 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001070
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001071 def test_set_default_verify_paths_signature(self):
1072 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001073 :py:obj:`Context.set_default_verify_paths` takes no arguments and
1074 raises :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001075 """
1076 context = Context(TLSv1_METHOD)
1077 self.assertRaises(TypeError, context.set_default_verify_paths, None)
1078 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
1079 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001080
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001081 def test_add_extra_chain_cert_invalid_cert(self):
1082 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001083 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if
1084 called with other than one argument or if called with an object which
1085 is not an instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001086 """
1087 context = Context(TLSv1_METHOD)
1088 self.assertRaises(TypeError, context.add_extra_chain_cert)
1089 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001090 self.assertRaises(
1091 TypeError, context.add_extra_chain_cert, object(), object()
1092 )
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001093
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001094 def _handshake_test(self, serverContext, clientContext):
1095 """
1096 Verify that a client and server created with the given contexts can
1097 successfully handshake and communicate.
1098 """
1099 serverSocket, clientSocket = socket_pair()
1100
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001101 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001102 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001103
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001104 client = Connection(clientContext, clientSocket)
1105 client.set_connect_state()
1106
1107 # Make them talk to each other.
1108 # self._interactInMemory(client, server)
1109 for i in range(3):
1110 for s in [client, server]:
1111 try:
1112 s.do_handshake()
1113 except WantReadError:
1114 pass
1115
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001116 def test_set_verify_callback_connection_argument(self):
1117 """
1118 The first argument passed to the verify callback is the
1119 :py:class:`Connection` instance for which verification is taking place.
1120 """
1121 serverContext = Context(TLSv1_METHOD)
1122 serverContext.use_privatekey(
1123 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1124 serverContext.use_certificate(
1125 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1126 serverConnection = Connection(serverContext, None)
1127
1128 class VerifyCallback(object):
1129 def callback(self, connection, *args):
1130 self.connection = connection
1131 return 1
1132
1133 verify = VerifyCallback()
1134 clientContext = Context(TLSv1_METHOD)
1135 clientContext.set_verify(VERIFY_PEER, verify.callback)
1136 clientConnection = Connection(clientContext, None)
1137 clientConnection.set_connect_state()
1138
1139 self._handshakeInMemory(clientConnection, serverConnection)
1140
1141 self.assertIdentical(verify.connection, clientConnection)
1142
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001143 def test_set_verify_callback_exception(self):
1144 """
1145 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1146 exception, verification fails and the exception is propagated to the
1147 caller of :py:obj:`Connection.do_handshake`.
1148 """
1149 serverContext = Context(TLSv1_METHOD)
1150 serverContext.use_privatekey(
1151 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1152 serverContext.use_certificate(
1153 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1154
1155 clientContext = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001156
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001157 def verify_callback(*args):
1158 raise Exception("silly verify failure")
1159 clientContext.set_verify(VERIFY_PEER, verify_callback)
1160
1161 exc = self.assertRaises(
1162 Exception, self._handshake_test, serverContext, clientContext)
1163 self.assertEqual("silly verify failure", str(exc))
1164
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001165 def test_add_extra_chain_cert(self):
1166 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001167 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509`
1168 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001169
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001170 See :py:obj:`_create_certificate_chain` for the details of the
1171 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001172
1173 The chain is tested by starting a server with scert and connecting
1174 to it with a client which trusts cacert and requires verification to
1175 succeed.
1176 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001177 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001178 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1179
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001180 # Dump the CA certificate to a file because that's the only way to load
1181 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001182 for cert, name in [(cacert, 'ca.pem'),
1183 (icert, 'i.pem'),
1184 (scert, 's.pem')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001185 with open(join(self.tmpdir, name), 'w') as f:
1186 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001187
Hynek Schlawack1902c012015-04-16 15:06:41 -04001188 for key, name in [(cakey, 'ca.key'),
1189 (ikey, 'i.key'),
1190 (skey, 's.key')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001191 with open(join(self.tmpdir, name), 'w') as f:
1192 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001193
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001194 # Create the server context
1195 serverContext = Context(TLSv1_METHOD)
1196 serverContext.use_privatekey(skey)
1197 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001198 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001199 serverContext.add_extra_chain_cert(icert)
1200
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001201 # Create the client
1202 clientContext = Context(TLSv1_METHOD)
1203 clientContext.set_verify(
1204 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001205 clientContext.load_verify_locations(join(self.tmpdir, "ca.pem"))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001206
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001207 # Try it out.
1208 self._handshake_test(serverContext, clientContext)
1209
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001210 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001211 """
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001212 Verify that :py:obj:`Context.use_certificate_chain_file` reads a
1213 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001214
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001215 The chain is tested by starting a server with scert and connecting to
1216 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001217 succeed.
1218 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001219 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001220 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1221
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001222 makedirs(certdir)
1223
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001224 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1225 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001226
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001227 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001228 with open(chainFile, 'wb') as fObj:
1229 # Most specific to least general.
1230 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1231 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1232 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1233
1234 with open(caFile, 'w') as fObj:
1235 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001236
1237 serverContext = Context(TLSv1_METHOD)
1238 serverContext.use_certificate_chain_file(chainFile)
1239 serverContext.use_privatekey(skey)
1240
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001241 clientContext = Context(TLSv1_METHOD)
1242 clientContext.set_verify(
1243 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001244 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001245
1246 self._handshake_test(serverContext, clientContext)
1247
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001248 def test_use_certificate_chain_file_bytes(self):
1249 """
1250 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1251 an instance of ``bytes``) to specify additional certificates to use to
1252 construct and verify a trust chain.
1253 """
1254 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001255 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001256 )
1257
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001258 def test_use_certificate_chain_file_unicode(self):
1259 """
1260 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1261 an instance of ``unicode``) to specify additional certificates to use
1262 to construct and verify a trust chain.
1263 """
1264 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001265 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001266 )
1267
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001268 def test_use_certificate_chain_file_wrong_args(self):
1269 """
1270 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1271 if passed zero or more than one argument or when passed a non-byte
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001272 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error`
1273 when passed a bad chain file name (for example, the name of a file
1274 which does not exist).
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001275 """
1276 context = Context(TLSv1_METHOD)
1277 self.assertRaises(TypeError, context.use_certificate_chain_file)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001278 self.assertRaises(
1279 TypeError, context.use_certificate_chain_file, object()
1280 )
1281 self.assertRaises(
1282 TypeError, context.use_certificate_chain_file, b"foo", object()
1283 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001284
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001285 self.assertRaises(
1286 Error, context.use_certificate_chain_file, self.mktemp()
1287 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001288
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001289 # XXX load_client_ca
1290 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001291
1292 def test_get_verify_mode_wrong_args(self):
1293 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001294 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called
1295 with any arguments.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001296 """
1297 context = Context(TLSv1_METHOD)
1298 self.assertRaises(TypeError, context.get_verify_mode, None)
1299
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001300 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001301 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001302 :py:obj:`Context.get_verify_mode` returns the verify mode flags
1303 previously passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001304 """
1305 context = Context(TLSv1_METHOD)
1306 self.assertEquals(context.get_verify_mode(), 0)
1307 context.set_verify(
1308 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1309 self.assertEquals(
1310 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1311
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001312 if not PY3:
1313 def test_set_verify_mode_long(self):
1314 """
1315 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1316 type :py:obj:`long` as well as :py:obj:`int`.
1317 """
1318 context = Context(TLSv1_METHOD)
1319 self.assertEquals(context.get_verify_mode(), 0)
1320 context.set_verify(
1321 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None)
1322 self.assertEquals(
1323 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1324
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001325 def test_load_tmp_dh_wrong_args(self):
1326 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001327 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with
1328 the wrong number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001329 """
1330 context = Context(TLSv1_METHOD)
1331 self.assertRaises(TypeError, context.load_tmp_dh)
1332 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1333 self.assertRaises(TypeError, context.load_tmp_dh, object())
1334
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001335 def test_load_tmp_dh_missing_file(self):
1336 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001337 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the
1338 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001339 """
1340 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001341 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001342
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001343 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001344 """
1345 Verify that calling ``Context.load_tmp_dh`` with the given filename
1346 does not raise an exception.
1347 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001348 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001349 with open(dhfilename, "w") as dhfile:
1350 dhfile.write(dhparam)
1351
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001352 context.load_tmp_dh(dhfilename)
1353 # XXX What should I assert here? -exarkun
1354
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001355 def test_load_tmp_dh_bytes(self):
1356 """
1357 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1358 specified file (given as ``bytes``).
1359 """
1360 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001361 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001362 )
1363
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001364 def test_load_tmp_dh_unicode(self):
1365 """
1366 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1367 specified file (given as ``unicode``).
1368 """
1369 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001370 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001371 )
1372
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001373 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001374 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001375 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001376 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001377 """
1378 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001379 for curve in get_elliptic_curves():
1380 # The only easily "assertable" thing is that it does not raise an
1381 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001382 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001383
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001384 def test_set_cipher_list_bytes(self):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001385 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001386 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
1387 ciphers which connections created with the context object will be able
1388 to choose from.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001389 """
1390 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001391 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001392 conn = Connection(context, None)
1393 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001394
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001395 def test_set_cipher_list_text(self):
1396 """
1397 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
1398 the ciphers which connections created with the context object will be
1399 able to choose from.
1400 """
1401 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -05001402 context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001403 conn = Connection(context, None)
1404 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
1405
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001406 def test_set_cipher_list_wrong_args(self):
1407 """
Jean-Paul Calderone17044832014-01-18 10:20:11 -05001408 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
1409 passed zero arguments or more than one argument or when passed a
1410 non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001411 passed an incorrect cipher list string.
1412 """
1413 context = Context(TLSv1_METHOD)
1414 self.assertRaises(TypeError, context.set_cipher_list)
1415 self.assertRaises(TypeError, context.set_cipher_list, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001416 self.assertRaises(
1417 TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object()
1418 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001419
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001420 self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001421
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001422 def test_set_session_cache_mode_wrong_args(self):
1423 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001424 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1425 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001426 """
1427 context = Context(TLSv1_METHOD)
1428 self.assertRaises(TypeError, context.set_session_cache_mode)
1429 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1430
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001431 def test_get_session_cache_mode_wrong_args(self):
1432 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001433 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1434 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001435 """
1436 context = Context(TLSv1_METHOD)
1437 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1438
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001439 def test_session_cache_mode(self):
1440 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001441 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1442 cached. The setting can be retrieved via
1443 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001444 """
1445 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001446 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001447 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1448 self.assertEqual(SESS_CACHE_OFF, off)
1449 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1450
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001451 if not PY3:
1452 def test_session_cache_mode_long(self):
1453 """
1454 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1455 of type :py:obj:`long` as well as :py:obj:`int`.
1456 """
1457 context = Context(TLSv1_METHOD)
1458 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1459 self.assertEqual(
1460 SESS_CACHE_BOTH, context.get_session_cache_mode())
1461
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001462 def test_get_cert_store(self):
1463 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001464 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store`
1465 instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001466 """
1467 context = Context(TLSv1_METHOD)
1468 store = context.get_cert_store()
1469 self.assertIsInstance(store, X509Store)
1470
1471
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001472class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1473 """
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 """
2155
2156 def attr_access_test(connection):
2157 return connection.an_attribute_which_is_not_defined
2158
2159 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)
2170 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04002171 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002172
2173
2174 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002175 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002176 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002177 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002178 port = socket()
2179 port.bind(('', 0))
2180 port.listen(3)
2181
2182 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002183 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2184 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002185
2186
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002187 if platform == "darwin":
2188 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2189 else:
2190 def test_connect_ex(self):
2191 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002192 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002193 errno instead of raising an exception.
2194 """
2195 port = socket()
2196 port.bind(('', 0))
2197 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002198
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002199 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2200 clientSSL.setblocking(False)
2201 result = clientSSL.connect_ex(port.getsockname())
2202 expected = (EINPROGRESS, EWOULDBLOCK)
2203 self.assertTrue(
2204 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002205
2206
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002207 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002208 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002209 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002210 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002211 connection = Connection(Context(TLSv1_METHOD), socket())
2212 self.assertRaises(TypeError, connection.accept, None)
2213
2214
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002215 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002216 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002217 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
2218 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002219 connection originated from.
2220 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002221 ctx = Context(TLSv1_METHOD)
2222 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2223 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002224 port = socket()
2225 portSSL = Connection(ctx, port)
2226 portSSL.bind(('', 0))
2227 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002228
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002229 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002230
2231 # Calling portSSL.getsockname() here to get the server IP address sounds
2232 # great, but frequently fails on Windows.
2233 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002234
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002235 serverSSL, address = portSSL.accept()
2236
2237 self.assertTrue(isinstance(serverSSL, Connection))
2238 self.assertIdentical(serverSSL.get_context(), ctx)
2239 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002240
2241
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002242 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002243 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002244 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002245 number of arguments or with arguments other than integers.
2246 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002247 connection = Connection(Context(TLSv1_METHOD), None)
2248 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04002249 self.assertRaises(TypeError, connection.get_shutdown, None)
2250 self.assertRaises(TypeError, connection.set_shutdown)
2251 self.assertRaises(TypeError, connection.set_shutdown, None)
2252 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002253
2254
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002255 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002256 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002257 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002258 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002259 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002260 self.assertFalse(server.shutdown())
2261 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002262 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002263 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
2264 client.shutdown()
Alex Gaynor43307782015-09-04 09:05:45 -04002265 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002266 self.assertRaises(ZeroReturnError, server.recv, 1024)
Alex Gaynor43307782015-09-04 09:05:45 -04002267 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002268
2269
Paul Aurichc85e0862015-01-08 08:34:33 -08002270 def test_shutdown_closed(self):
2271 """
2272 If the underlying socket is closed, :py:obj:`Connection.shutdown` propagates the
2273 write error from the low level write call.
2274 """
2275 server, client = self._loopback()
2276 server.sock_shutdown(2)
2277 exc = self.assertRaises(SysCallError, server.shutdown)
2278 if platform == "win32":
2279 self.assertEqual(exc.args[0], ESHUTDOWN)
2280 else:
2281 self.assertEqual(exc.args[0], EPIPE)
2282
2283
Glyph89389472015-04-14 17:29:26 -04002284 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002285 """
Glyph89389472015-04-14 17:29:26 -04002286 If the underlying connection is truncated, :obj:`Connection.shutdown`
2287 raises an :obj:`Error`.
Glyph6064ec32015-04-14 16:38:22 -04002288 """
Glyph89389472015-04-14 17:29:26 -04002289 server_ctx = Context(TLSv1_METHOD)
2290 client_ctx = Context(TLSv1_METHOD)
2291 server_ctx.use_privatekey(
2292 load_privatekey(FILETYPE_PEM, server_key_pem))
2293 server_ctx.use_certificate(
2294 load_certificate(FILETYPE_PEM, server_cert_pem))
2295 server = Connection(server_ctx, None)
2296 client = Connection(client_ctx, None)
2297 self._handshakeInMemory(client, server)
2298 self.assertEqual(server.shutdown(), False)
2299 self.assertRaises(WantReadError, server.shutdown)
2300 server.bio_shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002301 self.assertRaises(Error, server.shutdown)
2302
2303
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002304 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002305 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002306 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002307 process.
2308 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002309 connection = Connection(Context(TLSv1_METHOD), socket())
2310 connection.set_shutdown(RECEIVED_SHUTDOWN)
2311 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2312
2313
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002314 if not PY3:
2315 def test_set_shutdown_long(self):
2316 """
2317 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
2318 of type :py:obj:`long` as well as :py:obj:`int`.
2319 """
2320 connection = Connection(Context(TLSv1_METHOD), socket())
2321 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
2322 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2323
2324
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002325 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002326 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002327 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
2328 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002329 with any arguments.
2330 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002331 conn = Connection(Context(TLSv1_METHOD), None)
2332 self.assertRaises(TypeError, conn.get_app_data, None)
2333 self.assertRaises(TypeError, conn.set_app_data)
2334 self.assertRaises(TypeError, conn.set_app_data, None, None)
2335
2336
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002337 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002338 """
2339 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002340 :py:obj:`Connection.set_app_data` and later retrieved with
2341 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002342 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002343 conn = Connection(Context(TLSv1_METHOD), None)
2344 app_data = object()
2345 conn.set_app_data(app_data)
2346 self.assertIdentical(conn.get_app_data(), app_data)
2347
2348
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002349 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002350 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002351 :py:obj:`Connection.makefile` is not implemented and calling that method raises
2352 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002353 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002354 conn = Connection(Context(TLSv1_METHOD), None)
2355 self.assertRaises(NotImplementedError, conn.makefile)
2356
2357
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002358 def test_get_peer_cert_chain_wrong_args(self):
2359 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002360 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002361 arguments.
2362 """
2363 conn = Connection(Context(TLSv1_METHOD), None)
2364 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
2365 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
2366 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
2367 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
2368
2369
2370 def test_get_peer_cert_chain(self):
2371 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002372 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002373 the connected server returned for the certification verification.
2374 """
2375 chain = _create_certificate_chain()
2376 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2377
2378 serverContext = Context(TLSv1_METHOD)
2379 serverContext.use_privatekey(skey)
2380 serverContext.use_certificate(scert)
2381 serverContext.add_extra_chain_cert(icert)
2382 serverContext.add_extra_chain_cert(cacert)
2383 server = Connection(serverContext, None)
2384 server.set_accept_state()
2385
2386 # Create the client
2387 clientContext = Context(TLSv1_METHOD)
2388 clientContext.set_verify(VERIFY_NONE, verify_cb)
2389 client = Connection(clientContext, None)
2390 client.set_connect_state()
2391
2392 self._interactInMemory(client, server)
2393
2394 chain = client.get_peer_cert_chain()
2395 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002396 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002397 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002398 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002399 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002400 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002401 "Authority Certificate", chain[2].get_subject().CN)
2402
2403
2404 def test_get_peer_cert_chain_none(self):
2405 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002406 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002407 certificate chain.
2408 """
2409 ctx = Context(TLSv1_METHOD)
2410 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2411 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2412 server = Connection(ctx, None)
2413 server.set_accept_state()
2414 client = Connection(Context(TLSv1_METHOD), None)
2415 client.set_connect_state()
2416 self._interactInMemory(client, server)
2417 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002418
2419
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002420 def test_get_session_wrong_args(self):
2421 """
2422 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
2423 with any arguments.
2424 """
2425 ctx = Context(TLSv1_METHOD)
2426 server = Connection(ctx, None)
2427 self.assertRaises(TypeError, server.get_session, 123)
2428 self.assertRaises(TypeError, server.get_session, "hello")
2429 self.assertRaises(TypeError, server.get_session, object())
2430
2431
2432 def test_get_session_unconnected(self):
2433 """
2434 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
2435 an object which has not been connected.
2436 """
2437 ctx = Context(TLSv1_METHOD)
2438 server = Connection(ctx, None)
2439 session = server.get_session()
2440 self.assertIdentical(None, session)
2441
2442
2443 def test_server_get_session(self):
2444 """
2445 On the server side of a connection, :py:obj:`Connection.get_session`
2446 returns a :py:class:`Session` instance representing the SSL session for
2447 that connection.
2448 """
2449 server, client = self._loopback()
2450 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002451 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002452
2453
2454 def test_client_get_session(self):
2455 """
2456 On the client side of a connection, :py:obj:`Connection.get_session`
2457 returns a :py:class:`Session` instance representing the SSL session for
2458 that connection.
2459 """
2460 server, client = self._loopback()
2461 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002462 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002463
2464
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002465 def test_set_session_wrong_args(self):
2466 """
2467 If called with an object that is not an instance of :py:class:`Session`,
2468 or with other than one argument, :py:obj:`Connection.set_session` raises
2469 :py:obj:`TypeError`.
2470 """
2471 ctx = Context(TLSv1_METHOD)
2472 connection = Connection(ctx, None)
2473 self.assertRaises(TypeError, connection.set_session)
2474 self.assertRaises(TypeError, connection.set_session, 123)
2475 self.assertRaises(TypeError, connection.set_session, "hello")
2476 self.assertRaises(TypeError, connection.set_session, object())
2477 self.assertRaises(
2478 TypeError, connection.set_session, Session(), Session())
2479
2480
2481 def test_client_set_session(self):
2482 """
2483 :py:obj:`Connection.set_session`, when used prior to a connection being
2484 established, accepts a :py:class:`Session` instance and causes an
2485 attempt to re-use the session it represents when the SSL handshake is
2486 performed.
2487 """
2488 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2489 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2490 ctx = Context(TLSv1_METHOD)
2491 ctx.use_privatekey(key)
2492 ctx.use_certificate(cert)
2493 ctx.set_session_id("unity-test")
2494
2495 def makeServer(socket):
2496 server = Connection(ctx, socket)
2497 server.set_accept_state()
2498 return server
2499
2500 originalServer, originalClient = self._loopback(
2501 serverFactory=makeServer)
2502 originalSession = originalClient.get_session()
2503
2504 def makeClient(socket):
2505 client = self._loopbackClientFactory(socket)
2506 client.set_session(originalSession)
2507 return client
2508 resumedServer, resumedClient = self._loopback(
2509 serverFactory=makeServer,
2510 clientFactory=makeClient)
2511
2512 # This is a proxy: in general, we have no access to any unique
2513 # identifier for the session (new enough versions of OpenSSL expose a
2514 # hash which could be usable, but "new enough" is very, very new).
2515 # Instead, exploit the fact that the master key is re-used if the
2516 # session is re-used. As long as the master key for the two connections
2517 # is the same, the session was re-used!
2518 self.assertEqual(
2519 originalServer.master_key(), resumedServer.master_key())
2520
2521
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002522 def test_set_session_wrong_method(self):
2523 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002524 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
2525 instance associated with a context using a different SSL method than the
2526 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
2527 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002528 """
2529 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2530 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2531 ctx = Context(TLSv1_METHOD)
2532 ctx.use_privatekey(key)
2533 ctx.use_certificate(cert)
2534 ctx.set_session_id("unity-test")
2535
2536 def makeServer(socket):
2537 server = Connection(ctx, socket)
2538 server.set_accept_state()
2539 return server
2540
2541 originalServer, originalClient = self._loopback(
2542 serverFactory=makeServer)
2543 originalSession = originalClient.get_session()
2544
2545 def makeClient(socket):
2546 # Intentionally use a different, incompatible method here.
2547 client = Connection(Context(SSLv3_METHOD), socket)
2548 client.set_connect_state()
2549 client.set_session(originalSession)
2550 return client
2551
2552 self.assertRaises(
2553 Error,
2554 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2555
2556
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002557 def test_wantWriteError(self):
2558 """
2559 :py:obj:`Connection` methods which generate output raise
2560 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2561 fail indicating a should-write state.
2562 """
2563 client_socket, server_socket = socket_pair()
2564 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002565 # anything. Only write a single byte at a time so we can be sure we
2566 # completely fill the buffer. Even though the socket API is allowed to
2567 # signal a short write via its return value it seems this doesn't
2568 # always happen on all platforms (FreeBSD and OS X particular) for the
2569 # very last bit of available buffer space.
2570 msg = b"x"
2571 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002572 try:
2573 client_socket.send(msg)
2574 except error as e:
2575 if e.errno == EWOULDBLOCK:
2576 break
2577 raise
2578 else:
2579 self.fail(
2580 "Failed to fill socket buffer, cannot test BIO want write")
2581
2582 ctx = Context(TLSv1_METHOD)
2583 conn = Connection(ctx, client_socket)
2584 # Client's speak first, so make it an SSL client
2585 conn.set_connect_state()
2586 self.assertRaises(WantWriteError, conn.do_handshake)
2587
2588 # XXX want_read
2589
Fedor Brunner416f4a12014-03-28 13:18:38 +01002590 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002591 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002592 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2593 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002594 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002595 ctx = Context(TLSv1_METHOD)
2596 connection = Connection(ctx, None)
2597 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002598
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002599
Fedor Brunner416f4a12014-03-28 13:18:38 +01002600 def test_get_peer_finished_before_connect(self):
2601 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002602 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2603 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002604 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002605 ctx = Context(TLSv1_METHOD)
2606 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002607 self.assertEqual(connection.get_peer_finished(), None)
2608
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002609
Fedor Brunner416f4a12014-03-28 13:18:38 +01002610 def test_get_finished(self):
2611 """
2612 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002613 message send from client, or server. Finished messages are send during
2614 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002615 """
2616
Fedor Brunner5747b932014-03-05 14:22:34 +01002617 server, client = self._loopback()
2618
2619 self.assertNotEqual(server.get_finished(), None)
2620 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002621
Jean-Paul Calderoned979f232014-03-30 11:58:00 -04002622
Fedor Brunner416f4a12014-03-28 13:18:38 +01002623 def test_get_peer_finished(self):
2624 """
2625 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002626 message received from client, or server. Finished messages are send
2627 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002628 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002629 server, client = self._loopback()
2630
2631 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002632 self.assertTrue(len(server.get_peer_finished()) > 0)
2633
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002634
Fedor Brunner416f4a12014-03-28 13:18:38 +01002635 def test_tls_finished_message_symmetry(self):
2636 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002637 The TLS Finished message send by server must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002638 received by client.
2639
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002640 The TLS Finished message send by client must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002641 received by server.
2642 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002643 server, client = self._loopback()
2644
Fedor Brunner5747b932014-03-05 14:22:34 +01002645 self.assertEqual(server.get_finished(), client.get_peer_finished())
2646 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002647
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002648
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002649 def test_get_cipher_name_before_connect(self):
2650 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002651 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2652 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002653 """
2654 ctx = Context(TLSv1_METHOD)
2655 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002656 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002657
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002658
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002659 def test_get_cipher_name(self):
2660 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002661 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2662 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002663 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002664 server, client = self._loopback()
2665 server_cipher_name, client_cipher_name = \
2666 server.get_cipher_name(), client.get_cipher_name()
2667
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002668 self.assertIsInstance(server_cipher_name, text_type)
2669 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002670
2671 self.assertEqual(server_cipher_name, client_cipher_name)
2672
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002673
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002674 def test_get_cipher_version_before_connect(self):
2675 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002676 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2677 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002678 """
2679 ctx = Context(TLSv1_METHOD)
2680 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002681 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002682
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002683
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002684 def test_get_cipher_version(self):
2685 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002686 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2687 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002688 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002689 server, client = self._loopback()
2690 server_cipher_version, client_cipher_version = \
2691 server.get_cipher_version(), client.get_cipher_version()
2692
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002693 self.assertIsInstance(server_cipher_version, text_type)
2694 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002695
2696 self.assertEqual(server_cipher_version, client_cipher_version)
2697
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002698
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002699 def test_get_cipher_bits_before_connect(self):
2700 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002701 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2702 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002703 """
2704 ctx = Context(TLSv1_METHOD)
2705 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002706 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002707
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002708
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002709 def test_get_cipher_bits(self):
2710 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002711 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2712 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002713 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002714 server, client = self._loopback()
2715 server_cipher_bits, client_cipher_bits = \
2716 server.get_cipher_bits(), client.get_cipher_bits()
2717
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002718 self.assertIsInstance(server_cipher_bits, int)
2719 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002720
2721 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002722
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002723
Jim Shaverabff1882015-05-27 09:15:55 -04002724 def test_get_protocol_version_name(self):
2725 """
2726 :py:obj:`Connection.get_protocol_version_name()` returns a string
2727 giving the protocol version of the current connection.
2728 """
2729 server, client = self._loopback()
2730 client_protocol_version_name = client.get_protocol_version_name()
2731 server_protocol_version_name = server.get_protocol_version_name()
2732
Jim Shaver58d25732015-05-28 11:52:32 -04002733 self.assertIsInstance(server_protocol_version_name, text_type)
2734 self.assertIsInstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002735
2736 self.assertEqual(server_protocol_version_name, client_protocol_version_name)
2737
2738
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002739 def test_get_protocol_version(self):
2740 """
Alex Gaynor43307782015-09-04 09:05:45 -04002741 :py:obj:`Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002742 giving the protocol version of the current connection.
2743 """
2744 server, client = self._loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002745 client_protocol_version = client.get_protocol_version()
2746 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002747
Jim Shaverabff1882015-05-27 09:15:55 -04002748 self.assertIsInstance(server_protocol_version, int)
2749 self.assertIsInstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002750
2751 self.assertEqual(server_protocol_version, client_protocol_version)
2752
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002753
Jim Shaver208438c2015-05-28 09:52:38 -04002754
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002755class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002756 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002757 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002758 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002759 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002760 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002761 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002762 arguments.
2763 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002764 connection = Connection(Context(TLSv1_METHOD), None)
2765 self.assertRaises(TypeError, connection.get_cipher_list, None)
2766
2767
2768 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002769 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002770 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2771 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002772 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002773 connection = Connection(Context(TLSv1_METHOD), None)
2774 ciphers = connection.get_cipher_list()
2775 self.assertTrue(isinstance(ciphers, list))
2776 for cipher in ciphers:
2777 self.assertTrue(isinstance(cipher, str))
2778
2779
2780
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002781class ConnectionSendTests(TestCase, _LoopbackMixin):
2782 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002783 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002784 """
2785 def test_wrong_args(self):
2786 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002787 When called with arguments other than string argument for its first
2788 parameter or more than two arguments, :py:obj:`Connection.send` raises
2789 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002790 """
2791 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002792 self.assertRaises(TypeError, connection.send)
2793 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002794 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002795
2796
2797 def test_short_bytes(self):
2798 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002799 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002800 and returns the number of bytes sent.
2801 """
2802 server, client = self._loopback()
2803 count = server.send(b('xy'))
2804 self.assertEquals(count, 2)
2805 self.assertEquals(client.recv(2), b('xy'))
2806
Abraham Martinef063482015-03-25 14:06:24 +00002807
2808 def test_text(self):
2809 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002810 When passed a text, :py:obj:`Connection.send` transmits all of it and
2811 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002812 """
2813 server, client = self._loopback()
2814 with catch_warnings(record=True) as w:
2815 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002816 count = server.send(b"xy".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002817 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002818 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002819 WARNING_TYPE_EXPECTED
2820 ),
2821 str(w[-1].message)
2822 )
2823 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinef063482015-03-25 14:06:24 +00002824 self.assertEquals(count, 2)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002825 self.assertEquals(client.recv(2), b"xy")
Abraham Martinef063482015-03-25 14:06:24 +00002826
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002827 try:
2828 memoryview
2829 except NameError:
2830 "cannot test sending memoryview without memoryview"
2831 else:
2832 def test_short_memoryview(self):
2833 """
2834 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002835 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002836 bytes sent.
2837 """
2838 server, client = self._loopback()
2839 count = server.send(memoryview(b('xy')))
2840 self.assertEquals(count, 2)
2841 self.assertEquals(client.recv(2), b('xy'))
2842
2843
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002844 try:
2845 buffer
2846 except NameError:
2847 "cannot test sending buffer without buffer"
2848 else:
2849 def test_short_buffer(self):
2850 """
2851 When passed a buffer containing a small number of bytes,
2852 :py:obj:`Connection.send` transmits all of them and returns the number of
2853 bytes sent.
2854 """
2855 server, client = self._loopback()
2856 count = server.send(buffer(b('xy')))
2857 self.assertEquals(count, 2)
2858 self.assertEquals(client.recv(2), b('xy'))
2859
2860
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002861
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002862def _make_memoryview(size):
2863 """
2864 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2865 size.
2866 """
2867 return memoryview(bytearray(size))
2868
2869
2870
Cory Benfield62d10332014-06-15 10:03:41 +01002871class ConnectionRecvIntoTests(TestCase, _LoopbackMixin):
2872 """
2873 Tests for :py:obj:`Connection.recv_into`
2874 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002875 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002876 """
2877 Assert that when the given buffer is passed to
2878 ``Connection.recv_into``, whatever bytes are available to be received
2879 that fit into that buffer are written into that buffer.
2880 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002881 output_buffer = factory(5)
2882
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002883 server, client = self._loopback()
2884 server.send(b('xy'))
2885
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002886 self.assertEqual(client.recv_into(output_buffer), 2)
2887 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002888
2889
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002890 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002891 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002892 :py:obj:`Connection.recv_into` can be passed a ``bytearray`` instance
2893 and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002894 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002895 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002896
2897
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002898 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002899 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002900 Assert that when the given buffer is passed to ``Connection.recv_into``
2901 along with a value for ``nbytes`` that is less than the size of that
2902 buffer, only ``nbytes`` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002903 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002904 output_buffer = factory(10)
2905
Cory Benfield62d10332014-06-15 10:03:41 +01002906 server, client = self._loopback()
2907 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002908
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002909 self.assertEqual(client.recv_into(output_buffer, 5), 5)
2910 self.assertEqual(
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002911 output_buffer, bytearray(b('abcde\x00\x00\x00\x00\x00'))
2912 )
2913
2914
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002915 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002916 """
2917 When called with a ``bytearray`` instance,
2918 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter and
2919 doesn't copy in more than that number of bytes.
2920 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002921 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002922
2923
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002924 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002925 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002926 Assert that if there are more bytes available to be read from the
2927 receive buffer than would fit into the buffer passed to
2928 :py:obj:`Connection.recv_into`, only as many as fit are written into
2929 it.
Cory Benfield62d10332014-06-15 10:03:41 +01002930 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002931 output_buffer = factory(5)
2932
Cory Benfield62d10332014-06-15 10:03:41 +01002933 server, client = self._loopback()
2934 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002935
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002936 self.assertEqual(client.recv_into(output_buffer), 5)
2937 self.assertEqual(output_buffer, bytearray(b('abcde')))
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002938 rest = client.recv(5)
2939 self.assertEqual(b('fghij'), rest)
2940
2941
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002942 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002943 """
2944 When called with a ``bytearray`` instance,
2945 :py:obj:`Connection.recv_into` respects the size of the array and
2946 doesn't write more bytes into it than will fit.
2947 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002948 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002949
2950
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002951 def _really_doesnt_overfill_test(self, factory):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002952 """
2953 Assert that if the value given by ``nbytes`` is greater than the actual
2954 size of the output buffer passed to :py:obj:`Connection.recv_into`, the
2955 behavior is as if no value was given for ``nbytes`` at all.
2956 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002957 output_buffer = factory(5)
2958
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002959 server, client = self._loopback()
2960 server.send(b('abcdefghij'))
2961
2962 self.assertEqual(client.recv_into(output_buffer, 50), 5)
2963 self.assertEqual(output_buffer, bytearray(b('abcde')))
2964 rest = client.recv(5)
2965 self.assertEqual(b('fghij'), rest)
2966
2967
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002968 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002969 """
2970 When called with a ``bytearray`` instance and an ``nbytes`` value that
2971 is too large, :py:obj:`Connection.recv_into` respects the size of the
2972 array and not the ``nbytes`` value and doesn't write more bytes into
2973 the buffer than will fit.
2974 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002975 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002976
2977
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002978 def test_peek(self):
2979
2980 server, client = self._loopback()
2981 server.send(b('xy'))
2982
2983 for _ in range(2):
2984 output_buffer = bytearray(5)
2985 self.assertEqual(client.recv_into(output_buffer, flags=MSG_PEEK), 2)
2986 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
2987
2988
Cory Benfield62d10332014-06-15 10:03:41 +01002989 try:
2990 memoryview
2991 except NameError:
2992 "cannot test recv_into memoryview without memoryview"
2993 else:
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002994 def test_memoryview_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002995 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002996 :py:obj:`Connection.recv_into` can be passed a ``memoryview``
2997 instance and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002998 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002999 self._no_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003000
3001
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003002 def test_memoryview_respects_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01003003 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003004 When called with a ``memoryview`` instance,
3005 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter
3006 and doesn't copy more than that number of bytes in.
Cory Benfield62d10332014-06-15 10:03:41 +01003007 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003008 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003009
3010
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003011 def test_memoryview_doesnt_overfill(self):
Cory Benfield62d10332014-06-15 10:03:41 +01003012 """
Jean-Paul Calderone8fd82552015-03-15 17:21:07 -04003013 When called with a ``memoryview`` instance,
3014 :py:obj:`Connection.recv_into` respects the size of the array and
3015 doesn't write more bytes into it than will fit.
Cory Benfield62d10332014-06-15 10:03:41 +01003016 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003017 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003018
3019
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003020 def test_memoryview_really_doesnt_overfill(self):
3021 """
3022 When called with a ``memoryview`` instance and an ``nbytes`` value
3023 that is too large, :py:obj:`Connection.recv_into` respects the size
3024 of the array and not the ``nbytes`` value and doesn't write more
3025 bytes into the buffer than will fit.
3026 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003027 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003028
3029
Cory Benfield62d10332014-06-15 10:03:41 +01003030
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003031class ConnectionSendallTests(TestCase, _LoopbackMixin):
3032 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003033 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003034 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003035 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003036 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003037 When called with arguments other than a string argument for its first
3038 parameter or with more than two arguments, :py:obj:`Connection.sendall`
3039 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003040 """
3041 connection = Connection(Context(TLSv1_METHOD), None)
3042 self.assertRaises(TypeError, connection.sendall)
3043 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003044 self.assertRaises(
3045 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003046
3047
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003048 def test_short(self):
3049 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003050 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003051 it.
3052 """
3053 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04003054 server.sendall(b('x'))
3055 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003056
3057
Abraham Martinef063482015-03-25 14:06:24 +00003058 def test_text(self):
3059 """
Jean-Paul Calderone93477422015-04-13 20:38:57 -04003060 :py:obj:`Connection.sendall` transmits all the content in the string
3061 passed to it raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003062 """
3063 server, client = self._loopback()
3064 with catch_warnings(record=True) as w:
3065 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003066 server.sendall(b"x".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003067 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003068 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003069 WARNING_TYPE_EXPECTED
3070 ),
3071 str(w[-1].message)
3072 )
3073 self.assertIs(w[-1].category, DeprecationWarning)
3074 self.assertEquals(client.recv(1), b"x")
Abraham Martinef063482015-03-25 14:06:24 +00003075
3076
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003077 try:
3078 memoryview
3079 except NameError:
3080 "cannot test sending memoryview without memoryview"
3081 else:
3082 def test_short_memoryview(self):
3083 """
3084 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003085 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003086 """
3087 server, client = self._loopback()
3088 server.sendall(memoryview(b('x')))
3089 self.assertEquals(client.recv(1), b('x'))
3090
3091
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003092 try:
3093 buffer
3094 except NameError:
3095 "cannot test sending buffers without buffers"
3096 else:
3097 def test_short_buffers(self):
3098 """
3099 When passed a buffer containing a small number of bytes,
3100 :py:obj:`Connection.sendall` transmits all of them.
3101 """
3102 server, client = self._loopback()
3103 server.sendall(buffer(b('x')))
3104 self.assertEquals(client.recv(1), b('x'))
3105
3106
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003107 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003108 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003109 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003110 it even if this requires multiple calls of an underlying write function.
3111 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003112 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003113 # Should be enough, underlying SSL_write should only do 16k at a time.
3114 # On Windows, after 32k of bytes the write will block (forever - because
3115 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04003116 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003117 server.sendall(message)
3118 accum = []
3119 received = 0
3120 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003121 data = client.recv(1024)
3122 accum.append(data)
3123 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04003124 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003125
3126
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003127 def test_closed(self):
3128 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003129 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003130 write error from the low level write call.
3131 """
3132 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003133 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003134 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003135 if platform == "win32":
3136 self.assertEqual(exc.args[0], ESHUTDOWN)
3137 else:
3138 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003139
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003140
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04003141
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003142class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
3143 """
3144 Tests for SSL renegotiation APIs.
3145 """
3146 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003147 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003148 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003149 arguments.
3150 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003151 connection = Connection(Context(TLSv1_METHOD), None)
3152 self.assertRaises(TypeError, connection.renegotiate, None)
3153
3154
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003155 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003156 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003157 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003158 any arguments.
3159 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003160 connection = Connection(Context(TLSv1_METHOD), None)
3161 self.assertRaises(TypeError, connection.total_renegotiations, None)
3162
3163
3164 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003165 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003166 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003167 renegotiations have happened.
3168 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003169 connection = Connection(Context(TLSv1_METHOD), None)
3170 self.assertEquals(connection.total_renegotiations(), 0)
3171
3172
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003173# def test_renegotiate(self):
3174# """
3175# """
3176# server, client = self._loopback()
3177
3178# server.send("hello world")
3179# self.assertEquals(client.recv(len("hello world")), "hello world")
3180
3181# self.assertEquals(server.total_renegotiations(), 0)
3182# self.assertTrue(server.renegotiate())
3183
3184# server.setblocking(False)
3185# client.setblocking(False)
3186# while server.renegotiate_pending():
3187# client.do_handshake()
3188# server.do_handshake()
3189
3190# self.assertEquals(server.total_renegotiations(), 1)
3191
3192
3193
3194
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003195class ErrorTests(TestCase):
3196 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003197 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003198 """
3199 def test_type(self):
3200 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003201 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003202 """
3203 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05003204 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05003205
3206
3207
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003208class ConstantsTests(TestCase):
3209 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003210 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003211
3212 These are values defined by OpenSSL intended only to be used as flags to
3213 OpenSSL APIs. The only assertions it seems can be made about them is
3214 their values.
3215 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003216 # unittest.TestCase has no skip mechanism
3217 if OP_NO_QUERY_MTU is not None:
3218 def test_op_no_query_mtu(self):
3219 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003220 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003221 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003222 """
3223 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
3224 else:
3225 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003226
3227
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003228 if OP_COOKIE_EXCHANGE is not None:
3229 def test_op_cookie_exchange(self):
3230 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003231 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003232 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003233 """
3234 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
3235 else:
3236 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003237
3238
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003239 if OP_NO_TICKET is not None:
3240 def test_op_no_ticket(self):
3241 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003242 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003243 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003244 """
3245 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04003246 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003247 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05003248
3249
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003250 if OP_NO_COMPRESSION is not None:
3251 def test_op_no_compression(self):
3252 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003253 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
3254 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003255 """
3256 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
3257 else:
3258 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3259
3260
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003261 def test_sess_cache_off(self):
3262 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003263 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3264 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003265 """
3266 self.assertEqual(0x0, SESS_CACHE_OFF)
3267
3268
3269 def test_sess_cache_client(self):
3270 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003271 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3272 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003273 """
3274 self.assertEqual(0x1, SESS_CACHE_CLIENT)
3275
3276
3277 def test_sess_cache_server(self):
3278 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003279 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3280 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003281 """
3282 self.assertEqual(0x2, SESS_CACHE_SERVER)
3283
3284
3285 def test_sess_cache_both(self):
3286 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003287 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3288 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003289 """
3290 self.assertEqual(0x3, SESS_CACHE_BOTH)
3291
3292
3293 def test_sess_cache_no_auto_clear(self):
3294 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003295 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3296 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3297 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003298 """
3299 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
3300
3301
3302 def test_sess_cache_no_internal_lookup(self):
3303 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003304 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3305 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3306 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003307 """
3308 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
3309
3310
3311 def test_sess_cache_no_internal_store(self):
3312 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003313 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3314 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3315 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003316 """
3317 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
3318
3319
3320 def test_sess_cache_no_internal(self):
3321 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003322 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3323 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
3324 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003325 """
3326 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
3327
3328
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04003329
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003330class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05003331 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003332 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003333 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003334 def _server(self, sock):
3335 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003336 Create a new server-side SSL :py:obj:`Connection` object wrapped around
3337 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003338 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003339 # Create the server side Connection. This is mostly setup boilerplate
3340 # - use TLSv1, use a particular certificate, etc.
3341 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003342 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
3343 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 -04003344 server_store = server_ctx.get_cert_store()
3345 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3346 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3347 server_ctx.check_privatekey()
3348 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003349 # Here the Connection is actually created. If None is passed as the 2nd
3350 # parameter, it indicates a memory BIO should be created.
3351 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003352 server_conn.set_accept_state()
3353 return server_conn
3354
3355
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003356 def _client(self, sock):
3357 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003358 Create a new client-side SSL :py:obj:`Connection` object wrapped around
3359 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003360 """
3361 # Now create the client side Connection. Similar boilerplate to the
3362 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003363 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003364 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
3365 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 -04003366 client_store = client_ctx.get_cert_store()
3367 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
3368 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
3369 client_ctx.check_privatekey()
3370 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003371 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003372 client_conn.set_connect_state()
3373 return client_conn
3374
3375
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003376 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003377 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003378 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003379 reading from the output of each and writing those bytes to the input of
3380 the other and in this way establish a connection and exchange
3381 application-level bytes with each other.
3382 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003383 server_conn = self._server(None)
3384 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003385
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003386 # There should be no key or nonces yet.
3387 self.assertIdentical(server_conn.master_key(), None)
3388 self.assertIdentical(server_conn.client_random(), None)
3389 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003390
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003391 # First, the handshake needs to happen. We'll deliver bytes back and
3392 # forth between the client and server until neither of them feels like
3393 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003394 self.assertIdentical(
3395 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003396
3397 # Now that the handshake is done, there should be a key and nonces.
3398 self.assertNotIdentical(server_conn.master_key(), None)
3399 self.assertNotIdentical(server_conn.client_random(), None)
3400 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04003401 self.assertEquals(server_conn.client_random(), client_conn.client_random())
3402 self.assertEquals(server_conn.server_random(), client_conn.server_random())
3403 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
3404 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003405
3406 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003407 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05003408
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003409 server_conn.write(important_message)
3410 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003411 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003412 (client_conn, important_message))
3413
3414 client_conn.write(important_message[::-1])
3415 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003416 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003417 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003418
3419
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003420 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003421 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003422 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003423
3424 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09003425 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003426 this test fails, there must be a problem outside the memory BIO
3427 code, as no memory BIO is involved here). Even though this isn't a
3428 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003429 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04003430 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003431
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003432 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05003433 client_conn.send(important_message)
3434 msg = server_conn.recv(1024)
3435 self.assertEqual(msg, important_message)
3436
3437 # Again in the other direction, just for fun.
3438 important_message = important_message[::-1]
3439 server_conn.send(important_message)
3440 msg = client_conn.recv(1024)
3441 self.assertEqual(msg, important_message)
3442
3443
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04003444 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003445 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003446 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
3447 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003448 """
3449 context = Context(SSLv3_METHOD)
3450 client = socket()
3451 clientSSL = Connection(context, client)
Alex Gaynor43307782015-09-04 09:05:45 -04003452 self.assertRaises(TypeError, clientSSL.bio_read, 100)
3453 self.assertRaises(TypeError, clientSSL.bio_write, "foo")
Alex Gaynor7e8b61e2015-09-04 13:13:05 -04003454 self.assertRaises(TypeError, clientSSL.bio_shutdown)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003455
3456
3457 def test_outgoingOverflow(self):
3458 """
3459 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09003460 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003461 returned and that many bytes from the beginning of the input can be
3462 read from the other end of the connection.
3463 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003464 server = self._server(None)
3465 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003466
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003467 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003468
3469 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003470 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003471 # Sanity check. We're trying to test what happens when the entire
3472 # input can't be sent. If the entire input was sent, this test is
3473 # meaningless.
3474 self.assertTrue(sent < size)
3475
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003476 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003477 self.assertIdentical(receiver, server)
3478
3479 # We can rely on all of these bytes being received at once because
3480 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
3481 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003482
3483
3484 def test_shutdown(self):
3485 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003486 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
3487 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003488 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003489 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003490 server.bio_shutdown()
3491 e = self.assertRaises(Error, server.recv, 1024)
3492 # We don't want WantReadError or ZeroReturnError or anything - it's a
3493 # handshake failure.
3494 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003495
3496
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003497 def test_unexpectedEndOfFile(self):
3498 """
3499 If the connection is lost before an orderly SSL shutdown occurs,
3500 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
3501 "Unexpected EOF".
3502 """
3503 server_conn, client_conn = self._loopback()
3504 client_conn.sock_shutdown(SHUT_RDWR)
3505 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
3506 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
3507
3508
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003509 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003510 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003511 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 -04003512
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003513 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003514 before the client and server are connected to each other. This
3515 function should specify a list of CAs for the server to send to the
3516 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09003517 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003518 times.
3519 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003520 server = self._server(None)
3521 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003522 self.assertEqual(client.get_client_ca_list(), [])
3523 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003524 ctx = server.get_context()
3525 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003526 self.assertEqual(client.get_client_ca_list(), [])
3527 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003528 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003529 self.assertEqual(client.get_client_ca_list(), expected)
3530 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003531
3532
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003533 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003534 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003535 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003536 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003537 """
3538 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003539 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
3540 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
3541 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003542
3543
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003544 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003545 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003546 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003547 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09003548 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003549 after the connection is set up.
3550 """
3551 def no_ca(ctx):
3552 ctx.set_client_ca_list([])
3553 return []
3554 self._check_client_ca_list(no_ca)
3555
3556
3557 def test_set_one_ca_list(self):
3558 """
3559 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003560 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003561 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003562 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003563 X509Name after the connection is set up.
3564 """
3565 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3566 cadesc = cacert.get_subject()
3567 def single_ca(ctx):
3568 ctx.set_client_ca_list([cadesc])
3569 return [cadesc]
3570 self._check_client_ca_list(single_ca)
3571
3572
3573 def test_set_multiple_ca_list(self):
3574 """
3575 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003576 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003577 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003578 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003579 X509Names after the connection is set up.
3580 """
3581 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3582 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3583
3584 sedesc = secert.get_subject()
3585 cldesc = clcert.get_subject()
3586
3587 def multiple_ca(ctx):
3588 L = [sedesc, cldesc]
3589 ctx.set_client_ca_list(L)
3590 return L
3591 self._check_client_ca_list(multiple_ca)
3592
3593
3594 def test_reset_ca_list(self):
3595 """
3596 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09003597 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003598 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003599 """
3600 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3601 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3602 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3603
3604 cadesc = cacert.get_subject()
3605 sedesc = secert.get_subject()
3606 cldesc = clcert.get_subject()
3607
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003608 def changed_ca(ctx):
3609 ctx.set_client_ca_list([sedesc, cldesc])
3610 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003611 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003612 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003613
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003614
3615 def test_mutated_ca_list(self):
3616 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003617 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003618 afterwards, this does not affect the list of CA names sent to the
3619 client.
3620 """
3621 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3622 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3623
3624 cadesc = cacert.get_subject()
3625 sedesc = secert.get_subject()
3626
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003627 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003628 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003629 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003630 L.append(sedesc)
3631 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003632 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003633
3634
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003635 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003636 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003637 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003638 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003639 """
3640 ctx = Context(TLSv1_METHOD)
3641 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003642 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003643 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003644 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003645
3646
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003647 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003648 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003649 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09003650 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003651 """
3652 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3653 cadesc = cacert.get_subject()
3654 def single_ca(ctx):
3655 ctx.add_client_ca(cacert)
3656 return [cadesc]
3657 self._check_client_ca_list(single_ca)
3658
3659
3660 def test_multiple_add_client_ca(self):
3661 """
3662 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09003663 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003664 """
3665 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3666 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3667
3668 cadesc = cacert.get_subject()
3669 sedesc = secert.get_subject()
3670
3671 def multiple_ca(ctx):
3672 ctx.add_client_ca(cacert)
3673 ctx.add_client_ca(secert)
3674 return [cadesc, sedesc]
3675 self._check_client_ca_list(multiple_ca)
3676
3677
3678 def test_set_and_add_client_ca(self):
3679 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003680 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
3681 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003682 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003683 """
3684 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3685 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3686 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3687
3688 cadesc = cacert.get_subject()
3689 sedesc = secert.get_subject()
3690 cldesc = clcert.get_subject()
3691
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003692 def mixed_set_add_ca(ctx):
3693 ctx.set_client_ca_list([cadesc, sedesc])
3694 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003695 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003696 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003697
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003698
3699 def test_set_after_add_client_ca(self):
3700 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003701 A call to :py:obj:`Context.set_client_ca_list` after a call to
3702 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003703 call with the names specified by the latter cal.
3704 """
3705 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3706 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3707 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3708
3709 cadesc = cacert.get_subject()
3710 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003711
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003712 def set_replaces_add_ca(ctx):
3713 ctx.add_client_ca(clcert)
3714 ctx.set_client_ca_list([cadesc])
3715 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003716 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003717 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003718
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003719
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003720
3721class ConnectionBIOTests(TestCase):
3722 """
3723 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3724 """
3725 def test_wantReadError(self):
3726 """
3727 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
3728 if there are no bytes available to be read from the BIO.
3729 """
3730 ctx = Context(TLSv1_METHOD)
3731 conn = Connection(ctx, None)
3732 self.assertRaises(WantReadError, conn.bio_read, 1024)
3733
3734
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003735 def test_buffer_size(self):
3736 """
3737 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3738 number of bytes to read and return.
3739 """
3740 ctx = Context(TLSv1_METHOD)
3741 conn = Connection(ctx, None)
3742 conn.set_connect_state()
3743 try:
3744 conn.do_handshake()
3745 except WantReadError:
3746 pass
3747 data = conn.bio_read(2)
3748 self.assertEqual(2, len(data))
3749
3750
3751 if not PY3:
3752 def test_buffer_size_long(self):
3753 """
3754 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3755 :py:obj:`long` as well as :py:obj:`int`.
3756 """
3757 ctx = Context(TLSv1_METHOD)
3758 conn = Connection(ctx, None)
3759 conn.set_connect_state()
3760 try:
3761 conn.do_handshake()
3762 except WantReadError:
3763 pass
3764 data = conn.bio_read(long(2))
3765 self.assertEqual(2, len(data))
3766
3767
3768
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003769
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003770class InfoConstantTests(TestCase):
3771 """
3772 Tests for assorted constants exposed for use in info callbacks.
3773 """
3774 def test_integers(self):
3775 """
3776 All of the info constants are integers.
3777
3778 This is a very weak test. It would be nice to have one that actually
3779 verifies that as certain info events happen, the value passed to the
3780 info callback matches up with the constant exposed by OpenSSL.SSL.
3781 """
3782 for const in [
3783 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3784 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3785 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3786 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3787 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
3788 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
3789
3790 self.assertTrue(isinstance(const, int))
3791
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003792
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003793if __name__ == '__main__':
3794 main()