blob: f3a3a7cb8bed41a08b548ed8ce2ea6dc93b78be3 [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
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200102skip_if_py3 = pytest.mark.skipif(not PY3, reason="Python 2 only")
103
104
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400105def join_bytes_or_unicode(prefix, suffix):
106 """
107 Join two path components of either ``bytes`` or ``unicode``.
108
109 The return type is the same as the type of ``prefix``.
110 """
111 # If the types are the same, nothing special is necessary.
112 if type(prefix) == type(suffix):
113 return join(prefix, suffix)
114
115 # Otherwise, coerce suffix to the type of prefix.
116 if isinstance(prefix, text_type):
117 return join(prefix, suffix.decode(getfilesystemencoding()))
118 else:
119 return join(prefix, suffix.encode(getfilesystemencoding()))
120
121
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400122def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400123 return ok
124
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400125
Rick Deanb1ccd562009-07-09 23:52:39 -0500126def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400127 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400128 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400129 """
130 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500131 port = socket()
132 port.bind(('', 0))
133 port.listen(1)
134 client = socket()
135 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400136 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400137 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500138 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500139
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400140 # Let's pass some unencrypted data to make sure our socket connection is
141 # fine. Just one byte, so we don't have to worry about buffers getting
142 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400143 server.send(b("x"))
144 assert client.recv(1024) == b("x")
145 client.send(b("y"))
146 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500147
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400148 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400149 server.setblocking(False)
150 client.setblocking(False)
Jim Shaver46f28912015-05-29 19:32:16 -0400151
Rick Deanb1ccd562009-07-09 23:52:39 -0500152 return (server, client)
153
154
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400155def handshake(client, server):
156 conns = [client, server]
157 while conns:
158 for conn in conns:
159 try:
160 conn.do_handshake()
161 except WantReadError:
162 pass
163 else:
164 conns.remove(conn)
165
166
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400167def _create_certificate_chain():
168 """
169 Construct and return a chain of certificates.
170
171 1. A new self-signed certificate authority certificate (cacert)
172 2. A new intermediate certificate signed by cacert (icert)
173 3. A new server certificate signed by icert (scert)
174 """
175 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
176
177 # Step 1
178 cakey = PKey()
179 cakey.generate_key(TYPE_RSA, 512)
180 cacert = X509()
181 cacert.get_subject().commonName = "Authority Certificate"
182 cacert.set_issuer(cacert.get_subject())
183 cacert.set_pubkey(cakey)
184 cacert.set_notBefore(b("20000101000000Z"))
185 cacert.set_notAfter(b("20200101000000Z"))
186 cacert.add_extensions([caext])
187 cacert.set_serial_number(0)
188 cacert.sign(cakey, "sha1")
189
190 # Step 2
191 ikey = PKey()
192 ikey.generate_key(TYPE_RSA, 512)
193 icert = X509()
194 icert.get_subject().commonName = "Intermediate Certificate"
195 icert.set_issuer(cacert.get_subject())
196 icert.set_pubkey(ikey)
197 icert.set_notBefore(b("20000101000000Z"))
198 icert.set_notAfter(b("20200101000000Z"))
199 icert.add_extensions([caext])
200 icert.set_serial_number(0)
201 icert.sign(cakey, "sha1")
202
203 # Step 3
204 skey = PKey()
205 skey.generate_key(TYPE_RSA, 512)
206 scert = X509()
207 scert.get_subject().commonName = "Server Certificate"
208 scert.set_issuer(icert.get_subject())
209 scert.set_pubkey(skey)
210 scert.set_notBefore(b("20000101000000Z"))
211 scert.set_notAfter(b("20200101000000Z"))
212 scert.add_extensions([
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200213 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400214 scert.set_serial_number(0)
215 scert.sign(ikey, "sha1")
216
217 return [(cakey, cacert), (ikey, icert), (skey, scert)]
218
219
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400220class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400221 """
222 Helper mixin which defines methods for creating a connected socket pair and
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200223 for forcing two connected SSL sockets to talk to each other via memory
224 BIOs.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400225 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500226 def _loopbackClientFactory(self, socket):
227 client = Connection(Context(TLSv1_METHOD), socket)
228 client.set_connect_state()
229 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400230
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500231 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400232 ctx = Context(TLSv1_METHOD)
233 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
234 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500235 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400236 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500237 return server
238
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500239 def _loopback(self, serverFactory=None, clientFactory=None):
240 if serverFactory is None:
241 serverFactory = self._loopbackServerFactory
242 if clientFactory is None:
243 clientFactory = self._loopbackClientFactory
244
245 (server, client) = socket_pair()
246 server = serverFactory(server)
247 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400248
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400249 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400250
251 server.setblocking(True)
252 client.setblocking(True)
253 return server, client
254
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400255 def _interactInMemory(self, client_conn, server_conn):
256 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900257 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400258 objects. Copy bytes back and forth between their send/receive buffers
259 for as long as there is anything to copy. When there is nothing more
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200260 to copy, return :py:obj:`None`. If one of them actually manages to
261 deliver some application bytes, return a two-tuple of the connection
262 from which the bytes were read and the bytes themselves.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400263 """
264 wrote = True
265 while wrote:
266 # Loop until neither side has anything to say
267 wrote = False
268
269 # Copy stuff from each side's send buffer to the other side's
270 # receive buffer.
271 for (read, write) in [(client_conn, server_conn),
272 (server_conn, client_conn)]:
273
274 # Give the side a chance to generate some more bytes, or
275 # succeed.
276 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400277 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400278 except WantReadError:
279 # It didn't succeed, so we'll hope it generated some
280 # output.
281 pass
282 else:
283 # It did succeed, so we'll stop now and let the caller deal
284 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400285 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400286
287 while True:
288 # Keep copying as long as there's more stuff there.
289 try:
290 dirty = read.bio_read(4096)
291 except WantReadError:
292 # Okay, nothing more waiting to be sent. Stop
293 # processing this send buffer.
294 break
295 else:
296 # Keep track of the fact that someone generated some
297 # output.
298 wrote = True
299 write.bio_write(dirty)
300
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400301 def _handshakeInMemory(self, client_conn, server_conn):
Jean-Paul Calderoneb2b40782014-05-06 08:47:40 -0400302 """
303 Perform the TLS handshake between two :py:class:`Connection` instances
304 connected to each other via memory BIOs.
305 """
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400306 client_conn.set_connect_state()
307 server_conn.set_accept_state()
308
309 for conn in [client_conn, server_conn]:
310 try:
311 conn.do_handshake()
312 except WantReadError:
313 pass
314
315 self._interactInMemory(client_conn, server_conn)
316
317
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400318class VersionTests(TestCase):
319 """
320 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900321 :py:obj:`OpenSSL.SSL.SSLeay_version` and
322 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400323 """
324 def test_OPENSSL_VERSION_NUMBER(self):
325 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900326 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400327 byte and the patch, fix, minor, and major versions in the
328 nibbles above that.
329 """
330 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
331
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400332 def test_SSLeay_version(self):
333 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900334 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400335 one of a number of version strings based on that indicator.
336 """
337 versions = {}
338 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
339 SSLEAY_PLATFORM, SSLEAY_DIR]:
340 version = SSLeay_version(t)
341 versions[version] = t
342 self.assertTrue(isinstance(version, bytes))
343 self.assertEqual(len(versions), 5)
344
345
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400346class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400347 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900348 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400349 """
350 def test_method(self):
351 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200352 :py:obj:`Context` can be instantiated with one of
353 :py:obj:`SSLv2_METHOD`, :py:obj:`SSLv3_METHOD`,
354 :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400355 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400356 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400357 methods = [
358 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
359 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400360 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400361
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400362 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
363 for meth in maybe:
364 try:
365 Context(meth)
366 except (Error, ValueError):
367 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
368 # don't. Difficult to say in advance.
369 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400370
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400371 self.assertRaises(TypeError, Context, "")
372 self.assertRaises(ValueError, Context, 10)
373
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200374 @skip_if_py3
375 def test_method_long(self):
376 """
377 On Python 2 :py:class:`Context` accepts values of type
378 :py:obj:`long` as well as :py:obj:`int`.
379 """
380 Context(long(TLSv1_METHOD))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500381
Rick Deane15b1472009-07-09 15:53:42 -0500382 def test_type(self):
383 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200384 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type
385 object and can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500386 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400387 self.assertIdentical(Context, ContextType)
388 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500389
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400390 def test_use_privatekey(self):
391 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200392 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey`
393 instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400394 """
395 key = PKey()
396 key.generate_key(TYPE_RSA, 128)
397 ctx = Context(TLSv1_METHOD)
398 ctx.use_privatekey(key)
399 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400400
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800401 def test_use_privatekey_file_missing(self):
402 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200403 :py:obj:`Context.use_privatekey_file` raises
404 :py:obj:`OpenSSL.SSL.Error` when passed the name of a file which does
405 not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800406 """
407 ctx = Context(TLSv1_METHOD)
408 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
409
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400410 def _use_privatekey_file_test(self, pemfile, filetype):
411 """
412 Verify that calling ``Context.use_privatekey_file`` with the given
413 arguments does not raise an exception.
414 """
415 key = PKey()
416 key.generate_key(TYPE_RSA, 128)
417
418 with open(pemfile, "wt") as pem:
419 pem.write(
420 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
421 )
422
423 ctx = Context(TLSv1_METHOD)
424 ctx.use_privatekey_file(pemfile, filetype)
425
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400426 def test_use_privatekey_file_bytes(self):
427 """
428 A private key can be specified from a file by passing a ``bytes``
429 instance giving the file name to ``Context.use_privatekey_file``.
430 """
431 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400432 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400433 FILETYPE_PEM,
434 )
435
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400436 def test_use_privatekey_file_unicode(self):
437 """
438 A private key can be specified from a file by passing a ``unicode``
439 instance giving the file name to ``Context.use_privatekey_file``.
440 """
441 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400442 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400443 FILETYPE_PEM,
444 )
445
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200446 @skip_if_py3
447 def test_use_privatekey_file_long(self):
448 """
449 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
450 filetype of type :py:obj:`long` as well as :py:obj:`int`.
451 """
452 self._use_privatekey_file_test(self.mktemp(), long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500453
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800454 def test_use_certificate_wrong_args(self):
455 """
456 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200457 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as
458 an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800459 """
460 ctx = Context(TLSv1_METHOD)
461 self.assertRaises(TypeError, ctx.use_certificate)
462 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200463 self.assertRaises(
464 TypeError, ctx.use_certificate, X509(), "hello, world"
465 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800466
467 def test_use_certificate_uninitialized(self):
468 """
469 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
470 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
471 initialized (ie, which does not actually have any certificate data).
472 """
473 ctx = Context(TLSv1_METHOD)
474 self.assertRaises(Error, ctx.use_certificate, X509())
475
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800476 def test_use_certificate(self):
477 """
478 :py:obj:`Context.use_certificate` sets the certificate which will be
479 used to identify connections created using the context.
480 """
481 # TODO
482 # Hard to assert anything. But we could set a privatekey then ask
483 # OpenSSL if the cert and key agree using check_privatekey. Then as
484 # long as check_privatekey works right we're good...
485 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200486 ctx.use_certificate(
487 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
488 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800489
490 def test_use_certificate_file_wrong_args(self):
491 """
492 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
493 called with zero arguments or more than two arguments, or if the first
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200494 argument is not a byte string or the second argumnent is not an
495 integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800496 """
497 ctx = Context(TLSv1_METHOD)
498 self.assertRaises(TypeError, ctx.use_certificate_file)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200499 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile",
500 object())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800501 self.assertRaises(
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200502 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM,
503 object())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800504 self.assertRaises(
505 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
506 self.assertRaises(
507 TypeError, ctx.use_certificate_file, b"somefile", object())
508
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800509 def test_use_certificate_file_missing(self):
510 """
511 :py:obj:`Context.use_certificate_file` raises
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200512 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does
513 not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800514 """
515 ctx = Context(TLSv1_METHOD)
516 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
517
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400518 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800519 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400520 Verify that calling ``Context.use_certificate_file`` with the given
521 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800522 """
523 # TODO
524 # Hard to assert anything. But we could set a privatekey then ask
525 # OpenSSL if the cert and key agree using check_privatekey. Then as
526 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400527 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800528 pem_file.write(cleartextCertificatePEM)
529
530 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400531 ctx.use_certificate_file(certificate_file)
532
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400533 def test_use_certificate_file_bytes(self):
534 """
535 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
536 ``bytes`` filename) which will be used to identify connections created
537 using the context.
538 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400539 filename = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400540 self._use_certificate_file_test(filename)
541
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400542 def test_use_certificate_file_unicode(self):
543 """
544 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
545 ``bytes`` filename) which will be used to identify connections created
546 using the context.
547 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400548 filename = self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400549 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800550
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200551 @skip_if_py3
552 def test_use_certificate_file_long(self):
553 """
554 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
555 filetype of type :py:obj:`long` as well as :py:obj:`int`.
556 """
557 pem_filename = self.mktemp()
558 with open(pem_filename, "wb") as pem_file:
559 pem_file.write(cleartextCertificatePEM)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500560
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200561 ctx = Context(TLSv1_METHOD)
562 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500563
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500564 def test_check_privatekey_valid(self):
565 """
566 :py:obj:`Context.check_privatekey` returns :py:obj:`None` if the
567 :py:obj:`Context` instance has been configured to use a matched key and
568 certificate pair.
569 """
570 key = load_privatekey(FILETYPE_PEM, client_key_pem)
571 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
572 context = Context(TLSv1_METHOD)
573 context.use_privatekey(key)
574 context.use_certificate(cert)
575 self.assertIs(None, context.check_privatekey())
576
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500577 def test_check_privatekey_invalid(self):
578 """
579 :py:obj:`Context.check_privatekey` raises :py:obj:`Error` if the
580 :py:obj:`Context` instance has been configured to use a key and
581 certificate pair which don't relate to each other.
582 """
583 key = load_privatekey(FILETYPE_PEM, client_key_pem)
584 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
585 context = Context(TLSv1_METHOD)
586 context.use_privatekey(key)
587 context.use_certificate(cert)
588 self.assertRaises(Error, context.check_privatekey)
589
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500590 def test_check_privatekey_wrong_args(self):
591 """
592 :py:obj:`Context.check_privatekey` raises :py:obj:`TypeError` if called
593 with other than no arguments.
594 """
595 context = Context(TLSv1_METHOD)
596 self.assertRaises(TypeError, context.check_privatekey, object())
597
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400598 def test_set_app_data_wrong_args(self):
599 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200600 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called
601 with other than one argument.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400602 """
603 context = Context(TLSv1_METHOD)
604 self.assertRaises(TypeError, context.set_app_data)
605 self.assertRaises(TypeError, context.set_app_data, None, None)
606
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400607 def test_get_app_data_wrong_args(self):
608 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200609 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called
610 with any arguments.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400611 """
612 context = Context(TLSv1_METHOD)
613 self.assertRaises(TypeError, context.get_app_data, None)
614
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400615 def test_app_data(self):
616 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200617 :py:obj:`Context.set_app_data` stores an object for later retrieval
618 using :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400619 """
620 app_data = object()
621 context = Context(TLSv1_METHOD)
622 context.set_app_data(app_data)
623 self.assertIdentical(context.get_app_data(), app_data)
624
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400625 def test_set_options_wrong_args(self):
626 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200627 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with
628 the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400629 """
630 context = Context(TLSv1_METHOD)
631 self.assertRaises(TypeError, context.set_options)
632 self.assertRaises(TypeError, context.set_options, None)
633 self.assertRaises(TypeError, context.set_options, 1, None)
634
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500635 def test_set_options(self):
636 """
637 :py:obj:`Context.set_options` returns the new options value.
638 """
639 context = Context(TLSv1_METHOD)
640 options = context.set_options(OP_NO_SSLv2)
641 self.assertTrue(OP_NO_SSLv2 & options)
642
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200643 @skip_if_py3
644 def test_set_options_long(self):
645 """
646 On Python 2 :py:obj:`Context.set_options` accepts values of type
647 :py:obj:`long` as well as :py:obj:`int`.
648 """
649 context = Context(TLSv1_METHOD)
650 options = context.set_options(long(OP_NO_SSLv2))
651 self.assertTrue(OP_NO_SSLv2 & options)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500652
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300653 def test_set_mode_wrong_args(self):
654 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200655 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with
656 the wrong number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300657 """
658 context = Context(TLSv1_METHOD)
659 self.assertRaises(TypeError, context.set_mode)
660 self.assertRaises(TypeError, context.set_mode, None)
661 self.assertRaises(TypeError, context.set_mode, 1, None)
662
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400663 if MODE_RELEASE_BUFFERS is not None:
664 def test_set_mode(self):
665 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200666 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the
667 newly set mode.
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400668 """
669 context = Context(TLSv1_METHOD)
670 self.assertTrue(
671 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500672
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200673 @skip_if_py3
674 def test_set_mode_long(self):
675 """
676 On Python 2 :py:obj:`Context.set_mode` accepts values of type
677 :py:obj:`long` as well as :py:obj:`int`.
678 """
679 context = Context(TLSv1_METHOD)
680 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
681 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400682 else:
683 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
684
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400685 def test_set_timeout_wrong_args(self):
686 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200687 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with
688 the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400689 """
690 context = Context(TLSv1_METHOD)
691 self.assertRaises(TypeError, context.set_timeout)
692 self.assertRaises(TypeError, context.set_timeout, None)
693 self.assertRaises(TypeError, context.set_timeout, 1, None)
694
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400695 def test_get_timeout_wrong_args(self):
696 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200697 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with
698 any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400699 """
700 context = Context(TLSv1_METHOD)
701 self.assertRaises(TypeError, context.get_timeout, None)
702
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400703 def test_timeout(self):
704 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200705 :py:obj:`Context.set_timeout` sets the session timeout for all
706 connections created using the context object.
707 :py:obj:`Context.get_timeout` retrieves this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400708 """
709 context = Context(TLSv1_METHOD)
710 context.set_timeout(1234)
711 self.assertEquals(context.get_timeout(), 1234)
712
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200713 @skip_if_py3
714 def test_timeout_long(self):
715 """
716 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
717 `long` as well as int.
718 """
719 context = Context(TLSv1_METHOD)
720 context.set_timeout(long(1234))
721 self.assertEquals(context.get_timeout(), 1234)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500722
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400723 def test_set_verify_depth_wrong_args(self):
724 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200725 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called
726 with the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400727 """
728 context = Context(TLSv1_METHOD)
729 self.assertRaises(TypeError, context.set_verify_depth)
730 self.assertRaises(TypeError, context.set_verify_depth, None)
731 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
732
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400733 def test_get_verify_depth_wrong_args(self):
734 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200735 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called
736 with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400737 """
738 context = Context(TLSv1_METHOD)
739 self.assertRaises(TypeError, context.get_verify_depth, None)
740
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400741 def test_verify_depth(self):
742 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200743 :py:obj:`Context.set_verify_depth` sets the number of certificates in
744 a chain to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900745 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400746 """
747 context = Context(TLSv1_METHOD)
748 context.set_verify_depth(11)
749 self.assertEquals(context.get_verify_depth(), 11)
750
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200751 @skip_if_py3
752 def test_verify_depth_long(self):
753 """
754 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
755 type `long` as well as int.
756 """
757 context = Context(TLSv1_METHOD)
758 context.set_verify_depth(long(11))
759 self.assertEquals(context.get_verify_depth(), 11)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500760
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400761 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400762 """
763 Write a new private key out to a new file, encrypted using the given
764 passphrase. Return the path to the new file.
765 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400766 key = PKey()
767 key.generate_key(TYPE_RSA, 128)
768 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400769 fObj = open(pemFile, 'w')
770 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
771 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400772 fObj.close()
773 return pemFile
774
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400775 def test_set_passwd_cb_wrong_args(self):
776 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200777 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called
778 with the wrong arguments or with a non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400779 """
780 context = Context(TLSv1_METHOD)
781 self.assertRaises(TypeError, context.set_passwd_cb)
782 self.assertRaises(TypeError, context.set_passwd_cb, None)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200783 self.assertRaises(
784 TypeError, context.set_passwd_cb, lambda: None, None, None
Hynek Schlawack2c013a92015-09-05 19:33:05 +0200785 ) # pragma: nocover
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400786
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400787 def test_set_passwd_cb(self):
788 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200789 :py:obj:`Context.set_passwd_cb` accepts a callable which will be
790 invoked when a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400791 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400792 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400793 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400794 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200795
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400796 def passphraseCallback(maxlen, verify, extra):
797 calledWith.append((maxlen, verify, extra))
798 return passphrase
799 context = Context(TLSv1_METHOD)
800 context.set_passwd_cb(passphraseCallback)
801 context.use_privatekey_file(pemFile)
802 self.assertTrue(len(calledWith), 1)
803 self.assertTrue(isinstance(calledWith[0][0], int))
804 self.assertTrue(isinstance(calledWith[0][1], int))
805 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400806
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400807 def test_passwd_callback_exception(self):
808 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200809 :py:obj:`Context.use_privatekey_file` propagates any exception raised
810 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400811 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400812 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200813
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400814 def passphraseCallback(maxlen, verify, extra):
815 raise RuntimeError("Sorry, I am a fail.")
816
817 context = Context(TLSv1_METHOD)
818 context.set_passwd_cb(passphraseCallback)
819 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
820
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400821 def test_passwd_callback_false(self):
822 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200823 :py:obj:`Context.use_privatekey_file` raises
824 :py:obj:`OpenSSL.SSL.Error` if the passphrase callback returns a false
825 value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400826 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400827 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200828
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400829 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500830 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400831
832 context = Context(TLSv1_METHOD)
833 context.set_passwd_cb(passphraseCallback)
834 self.assertRaises(Error, context.use_privatekey_file, pemFile)
835
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400836 def test_passwd_callback_non_string(self):
837 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200838 :py:obj:`Context.use_privatekey_file` raises
839 :py:obj:`OpenSSL.SSL.Error` if the passphrase callback returns a true
840 non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400841 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400842 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200843
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400844 def passphraseCallback(maxlen, verify, extra):
845 return 10
846
847 context = Context(TLSv1_METHOD)
848 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800849 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400850
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400851 def test_passwd_callback_too_long(self):
852 """
853 If the passphrase returned by the passphrase callback returns a string
854 longer than the indicated maximum length, it is truncated.
855 """
856 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400857 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400858 pemFile = self._write_encrypted_pem(passphrase)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200859
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400860 def passphraseCallback(maxlen, verify, extra):
861 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400862 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400863
864 context = Context(TLSv1_METHOD)
865 context.set_passwd_cb(passphraseCallback)
866 # This shall succeed because the truncated result is the correct
867 # passphrase.
868 context.use_privatekey_file(pemFile)
869
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400870 def test_set_info_callback(self):
871 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200872 :py:obj:`Context.set_info_callback` accepts a callable which will be
873 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400874 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500875 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400876
877 clientSSL = Connection(Context(TLSv1_METHOD), client)
878 clientSSL.set_connect_state()
879
880 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200881
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400882 def info(conn, where, ret):
883 called.append((conn, where, ret))
884 context = Context(TLSv1_METHOD)
885 context.set_info_callback(info)
886 context.use_certificate(
887 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
888 context.use_privatekey(
889 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
890
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400891 serverSSL = Connection(context, server)
892 serverSSL.set_accept_state()
893
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500894 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400895
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500896 # The callback must always be called with a Connection instance as the
897 # first argument. It would probably be better to split this into
898 # separate tests for client and server side info callbacks so we could
899 # assert it is called with the right Connection instance. It would
900 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500901 notConnections = [
902 conn for (conn, where, ret) in called
903 if not isinstance(conn, Connection)]
904 self.assertEqual(
905 [], notConnections,
906 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400907
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400908 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400909 """
910 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400911 its :py:obj:`load_verify_locations` method with the given arguments.
912 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400913 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500914 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400915
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400916 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400917 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400918 # Require that the server certificate verify properly or the
919 # connection will fail.
920 clientContext.set_verify(
921 VERIFY_PEER,
922 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
923
924 clientSSL = Connection(clientContext, client)
925 clientSSL.set_connect_state()
926
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400927 serverContext = Context(TLSv1_METHOD)
928 serverContext.use_certificate(
929 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
930 serverContext.use_privatekey(
931 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
932
933 serverSSL = Connection(serverContext, server)
934 serverSSL.set_accept_state()
935
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400936 # Without load_verify_locations above, the handshake
937 # will fail:
938 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
939 # 'certificate verify failed')]
940 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400941
942 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400943 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400944
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400945 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400946 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400947 Verify that if path to a file containing a certificate is passed to
948 ``Context.load_verify_locations`` for the ``cafile`` parameter, that
949 certificate is used as a trust root for the purposes of verifying
950 connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400951 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400952 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400953 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400954 fObj.close()
955
956 self._load_verify_locations_test(cafile)
957
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400958 def test_load_verify_bytes_cafile(self):
959 """
960 :py:obj:`Context.load_verify_locations` accepts a file name as a
961 ``bytes`` instance and uses the certificates within for verification
962 purposes.
963 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400964 cafile = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400965 self._load_verify_cafile(cafile)
966
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400967 def test_load_verify_unicode_cafile(self):
968 """
969 :py:obj:`Context.load_verify_locations` accepts a file name as a
970 ``unicode`` instance and uses the certificates within for verification
971 purposes.
972 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -0400973 self._load_verify_cafile(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400974 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -0400975 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400976
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400977 def test_load_verify_invalid_file(self):
978 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200979 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when
980 passed a non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400981 """
982 clientContext = Context(TLSv1_METHOD)
983 self.assertRaises(
984 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400985
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400986 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400987 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400988 Verify that if path to a directory containing certificate files is
989 passed to ``Context.load_verify_locations`` for the ``capath``
990 parameter, those certificates are used as trust roots for the purposes
991 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400992 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400993 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400994 # Hash values computed manually with c_rehash to avoid depending on
995 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
996 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500997 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400998 cafile = join_bytes_or_unicode(capath, name)
999 with open(cafile, 'w') as fObj:
1000 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001001
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001002 self._load_verify_locations_test(None, capath)
1003
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001004 def test_load_verify_directory_bytes_capath(self):
1005 """
1006 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1007 ``bytes`` instance and uses the certificates within for verification
1008 purposes.
1009 """
1010 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001011 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001012 )
1013
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001014 def test_load_verify_directory_unicode_capath(self):
1015 """
1016 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1017 ``unicode`` instance and uses the certificates within for verification
1018 purposes.
1019 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001020 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001021 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001022 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001023
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001024 def test_load_verify_locations_wrong_args(self):
1025 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001026 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if
1027 called with the wrong number of arguments or with non-:py:obj:`str`
1028 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001029 """
1030 context = Context(TLSv1_METHOD)
1031 self.assertRaises(TypeError, context.load_verify_locations)
1032 self.assertRaises(TypeError, context.load_verify_locations, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001033 self.assertRaises(
1034 TypeError, context.load_verify_locations, object(), object()
1035 )
1036 self.assertRaises(
1037 TypeError, context.load_verify_locations, None, None, None
1038 )
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001039
Hynek Schlawack734d3022015-09-05 19:19:32 +02001040 @pytest.mark.skipif(
1041 platform == "win32",
1042 reason="set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001043 "See LP#404343 and LP#404344."
Hynek Schlawack734d3022015-09-05 19:19:32 +02001044 )
1045 def test_set_default_verify_paths(self):
1046 """
1047 :py:obj:`Context.set_default_verify_paths` causes the
1048 platform-specific CA certificate locations to be used for
1049 verification purposes.
1050 """
1051 # Testing this requires a server with a certificate signed by one
1052 # of the CAs in the platform CA location. Getting one of those
1053 # costs money. Fortunately (or unfortunately, depending on your
1054 # perspective), it's easy to think of a public server on the
1055 # internet which has such a certificate. Connecting to the network
1056 # in a unit test is bad, but it's the only way I can think of to
1057 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001058
Hynek Schlawack734d3022015-09-05 19:19:32 +02001059 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
1060 context = Context(TLSv1_METHOD)
1061 context.set_default_verify_paths()
1062 context.set_verify(
1063 VERIFY_PEER,
1064 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001065
Hynek Schlawack734d3022015-09-05 19:19:32 +02001066 client = socket()
1067 client.connect(('verisign.com', 443))
1068 clientSSL = Connection(context, client)
1069 clientSSL.set_connect_state()
1070 clientSSL.do_handshake()
1071 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
1072 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001073
1074 def test_set_default_verify_paths_signature(self):
1075 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001076 :py:obj:`Context.set_default_verify_paths` takes no arguments and
1077 raises :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001078 """
1079 context = Context(TLSv1_METHOD)
1080 self.assertRaises(TypeError, context.set_default_verify_paths, None)
1081 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
1082 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001083
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001084 def test_add_extra_chain_cert_invalid_cert(self):
1085 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001086 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if
1087 called with other than one argument or if called with an object which
1088 is not an instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001089 """
1090 context = Context(TLSv1_METHOD)
1091 self.assertRaises(TypeError, context.add_extra_chain_cert)
1092 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001093 self.assertRaises(
1094 TypeError, context.add_extra_chain_cert, object(), object()
1095 )
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001096
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001097 def _handshake_test(self, serverContext, clientContext):
1098 """
1099 Verify that a client and server created with the given contexts can
1100 successfully handshake and communicate.
1101 """
1102 serverSocket, clientSocket = socket_pair()
1103
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001104 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001105 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001106
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001107 client = Connection(clientContext, clientSocket)
1108 client.set_connect_state()
1109
1110 # Make them talk to each other.
1111 # self._interactInMemory(client, server)
1112 for i in range(3):
1113 for s in [client, server]:
1114 try:
1115 s.do_handshake()
1116 except WantReadError:
1117 pass
1118
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001119 def test_set_verify_callback_connection_argument(self):
1120 """
1121 The first argument passed to the verify callback is the
1122 :py:class:`Connection` instance for which verification is taking place.
1123 """
1124 serverContext = Context(TLSv1_METHOD)
1125 serverContext.use_privatekey(
1126 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1127 serverContext.use_certificate(
1128 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1129 serverConnection = Connection(serverContext, None)
1130
1131 class VerifyCallback(object):
1132 def callback(self, connection, *args):
1133 self.connection = connection
1134 return 1
1135
1136 verify = VerifyCallback()
1137 clientContext = Context(TLSv1_METHOD)
1138 clientContext.set_verify(VERIFY_PEER, verify.callback)
1139 clientConnection = Connection(clientContext, None)
1140 clientConnection.set_connect_state()
1141
1142 self._handshakeInMemory(clientConnection, serverConnection)
1143
1144 self.assertIdentical(verify.connection, clientConnection)
1145
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001146 def test_set_verify_callback_exception(self):
1147 """
1148 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1149 exception, verification fails and the exception is propagated to the
1150 caller of :py:obj:`Connection.do_handshake`.
1151 """
1152 serverContext = Context(TLSv1_METHOD)
1153 serverContext.use_privatekey(
1154 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1155 serverContext.use_certificate(
1156 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1157
1158 clientContext = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001159
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001160 def verify_callback(*args):
1161 raise Exception("silly verify failure")
1162 clientContext.set_verify(VERIFY_PEER, verify_callback)
1163
1164 exc = self.assertRaises(
1165 Exception, self._handshake_test, serverContext, clientContext)
1166 self.assertEqual("silly verify failure", str(exc))
1167
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001168 def test_add_extra_chain_cert(self):
1169 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001170 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509`
1171 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001172
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001173 See :py:obj:`_create_certificate_chain` for the details of the
1174 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001175
1176 The chain is tested by starting a server with scert and connecting
1177 to it with a client which trusts cacert and requires verification to
1178 succeed.
1179 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001180 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001181 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1182
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001183 # Dump the CA certificate to a file because that's the only way to load
1184 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001185 for cert, name in [(cacert, 'ca.pem'),
1186 (icert, 'i.pem'),
1187 (scert, 's.pem')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001188 with open(join(self.tmpdir, name), 'w') as f:
1189 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001190
Hynek Schlawack1902c012015-04-16 15:06:41 -04001191 for key, name in [(cakey, 'ca.key'),
1192 (ikey, 'i.key'),
1193 (skey, 's.key')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001194 with open(join(self.tmpdir, name), 'w') as f:
1195 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001196
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001197 # Create the server context
1198 serverContext = Context(TLSv1_METHOD)
1199 serverContext.use_privatekey(skey)
1200 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001201 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001202 serverContext.add_extra_chain_cert(icert)
1203
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001204 # Create the client
1205 clientContext = Context(TLSv1_METHOD)
1206 clientContext.set_verify(
1207 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001208 clientContext.load_verify_locations(join(self.tmpdir, "ca.pem"))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001209
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001210 # Try it out.
1211 self._handshake_test(serverContext, clientContext)
1212
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001213 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001214 """
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001215 Verify that :py:obj:`Context.use_certificate_chain_file` reads a
1216 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001217
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001218 The chain is tested by starting a server with scert and connecting to
1219 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001220 succeed.
1221 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001222 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001223 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1224
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001225 makedirs(certdir)
1226
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001227 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1228 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001229
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001230 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001231 with open(chainFile, 'wb') as fObj:
1232 # Most specific to least general.
1233 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1234 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1235 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1236
1237 with open(caFile, 'w') as fObj:
1238 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001239
1240 serverContext = Context(TLSv1_METHOD)
1241 serverContext.use_certificate_chain_file(chainFile)
1242 serverContext.use_privatekey(skey)
1243
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001244 clientContext = Context(TLSv1_METHOD)
1245 clientContext.set_verify(
1246 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001247 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001248
1249 self._handshake_test(serverContext, clientContext)
1250
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001251 def test_use_certificate_chain_file_bytes(self):
1252 """
1253 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1254 an instance of ``bytes``) to specify additional certificates to use to
1255 construct and verify a trust chain.
1256 """
1257 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001258 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001259 )
1260
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001261 def test_use_certificate_chain_file_unicode(self):
1262 """
1263 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1264 an instance of ``unicode``) to specify additional certificates to use
1265 to construct and verify a trust chain.
1266 """
1267 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001268 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001269 )
1270
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001271 def test_use_certificate_chain_file_wrong_args(self):
1272 """
1273 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1274 if passed zero or more than one argument or when passed a non-byte
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001275 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error`
1276 when passed a bad chain file name (for example, the name of a file
1277 which does not exist).
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001278 """
1279 context = Context(TLSv1_METHOD)
1280 self.assertRaises(TypeError, context.use_certificate_chain_file)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001281 self.assertRaises(
1282 TypeError, context.use_certificate_chain_file, object()
1283 )
1284 self.assertRaises(
1285 TypeError, context.use_certificate_chain_file, b"foo", object()
1286 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001287
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001288 self.assertRaises(
1289 Error, context.use_certificate_chain_file, self.mktemp()
1290 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001291
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001292 # XXX load_client_ca
1293 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001294
1295 def test_get_verify_mode_wrong_args(self):
1296 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001297 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called
1298 with any arguments.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001299 """
1300 context = Context(TLSv1_METHOD)
1301 self.assertRaises(TypeError, context.get_verify_mode, None)
1302
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001303 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001304 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001305 :py:obj:`Context.get_verify_mode` returns the verify mode flags
1306 previously passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001307 """
1308 context = Context(TLSv1_METHOD)
1309 self.assertEquals(context.get_verify_mode(), 0)
1310 context.set_verify(
1311 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1312 self.assertEquals(
1313 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1314
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001315 @skip_if_py3
1316 def test_set_verify_mode_long(self):
1317 """
1318 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1319 type :py:obj:`long` as well as :py:obj:`int`.
1320 """
1321 context = Context(TLSv1_METHOD)
1322 self.assertEquals(context.get_verify_mode(), 0)
1323 context.set_verify(
1324 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None)
1325 self.assertEquals(
1326 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001327
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001328 def test_load_tmp_dh_wrong_args(self):
1329 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001330 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with
1331 the wrong number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001332 """
1333 context = Context(TLSv1_METHOD)
1334 self.assertRaises(TypeError, context.load_tmp_dh)
1335 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1336 self.assertRaises(TypeError, context.load_tmp_dh, object())
1337
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001338 def test_load_tmp_dh_missing_file(self):
1339 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001340 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the
1341 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001342 """
1343 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001344 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001345
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001346 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001347 """
1348 Verify that calling ``Context.load_tmp_dh`` with the given filename
1349 does not raise an exception.
1350 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001351 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001352 with open(dhfilename, "w") as dhfile:
1353 dhfile.write(dhparam)
1354
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001355 context.load_tmp_dh(dhfilename)
1356 # XXX What should I assert here? -exarkun
1357
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001358 def test_load_tmp_dh_bytes(self):
1359 """
1360 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1361 specified file (given as ``bytes``).
1362 """
1363 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001364 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001365 )
1366
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001367 def test_load_tmp_dh_unicode(self):
1368 """
1369 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1370 specified file (given as ``unicode``).
1371 """
1372 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001373 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001374 )
1375
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001376 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001377 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001378 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001379 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001380 """
1381 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001382 for curve in get_elliptic_curves():
1383 # The only easily "assertable" thing is that it does not raise an
1384 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001385 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001386
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001387 def test_set_cipher_list_bytes(self):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001388 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001389 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
1390 ciphers which connections created with the context object will be able
1391 to choose from.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001392 """
1393 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001394 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001395 conn = Connection(context, None)
1396 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001397
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001398 def test_set_cipher_list_text(self):
1399 """
1400 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
1401 the ciphers which connections created with the context object will be
1402 able to choose from.
1403 """
1404 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -05001405 context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001406 conn = Connection(context, None)
1407 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
1408
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001409 def test_set_cipher_list_wrong_args(self):
1410 """
Jean-Paul Calderone17044832014-01-18 10:20:11 -05001411 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
1412 passed zero arguments or more than one argument or when passed a
1413 non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001414 passed an incorrect cipher list string.
1415 """
1416 context = Context(TLSv1_METHOD)
1417 self.assertRaises(TypeError, context.set_cipher_list)
1418 self.assertRaises(TypeError, context.set_cipher_list, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001419 self.assertRaises(
1420 TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object()
1421 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001422
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001423 self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001424
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001425 def test_set_session_cache_mode_wrong_args(self):
1426 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001427 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1428 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001429 """
1430 context = Context(TLSv1_METHOD)
1431 self.assertRaises(TypeError, context.set_session_cache_mode)
1432 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1433
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001434 def test_get_session_cache_mode_wrong_args(self):
1435 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001436 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1437 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001438 """
1439 context = Context(TLSv1_METHOD)
1440 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1441
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001442 def test_session_cache_mode(self):
1443 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001444 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1445 cached. The setting can be retrieved via
1446 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001447 """
1448 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001449 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001450 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1451 self.assertEqual(SESS_CACHE_OFF, off)
1452 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1453
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001454 @skip_if_py3
1455 def test_session_cache_mode_long(self):
1456 """
1457 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1458 of type :py:obj:`long` as well as :py:obj:`int`.
1459 """
1460 context = Context(TLSv1_METHOD)
1461 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1462 self.assertEqual(
1463 SESS_CACHE_BOTH, context.get_session_cache_mode())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001464
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001465 def test_get_cert_store(self):
1466 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001467 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store`
1468 instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001469 """
1470 context = Context(TLSv1_METHOD)
1471 store = context.get_cert_store()
1472 self.assertIsInstance(store, X509Store)
1473
1474
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001475class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1476 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001477 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its
1478 interaction with :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001479 """
1480 def test_wrong_args(self):
1481 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001482 :py:obj:`Context.set_tlsext_servername_callback` raises
1483 :py:obj:`TypeError` if called with other than one argument.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001484 """
1485 context = Context(TLSv1_METHOD)
1486 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1487 self.assertRaises(
1488 TypeError, context.set_tlsext_servername_callback, 1, 2)
1489
1490 def test_old_callback_forgotten(self):
1491 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001492 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify
1493 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001494 """
1495 def callback(connection):
1496 pass
1497
1498 def replacement(connection):
1499 pass
1500
1501 context = Context(TLSv1_METHOD)
1502 context.set_tlsext_servername_callback(callback)
1503
1504 tracker = ref(callback)
1505 del callback
1506
1507 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001508
1509 # One run of the garbage collector happens to work on CPython. PyPy
1510 # doesn't collect the underlying object until a second run for whatever
1511 # reason. That's fine, it still demonstrates our code has properly
1512 # dropped the reference.
1513 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001514 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001515
1516 callback = tracker()
1517 if callback is not None:
1518 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001519 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001520 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001521
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001522 def test_no_servername(self):
1523 """
1524 When a client specifies no server name, the callback passed to
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001525 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the
1526 result of :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001527 """
1528 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001529
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001530 def servername(conn):
1531 args.append((conn, conn.get_servername()))
1532 context = Context(TLSv1_METHOD)
1533 context.set_tlsext_servername_callback(servername)
1534
1535 # Lose our reference to it. The Context is responsible for keeping it
1536 # alive now.
1537 del servername
1538 collect()
1539
1540 # Necessary to actually accept the connection
1541 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001542 context.use_certificate(
1543 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001544
1545 # Do a little connection to trigger the logic
1546 server = Connection(context, None)
1547 server.set_accept_state()
1548
1549 client = Connection(Context(TLSv1_METHOD), None)
1550 client.set_connect_state()
1551
1552 self._interactInMemory(server, client)
1553
1554 self.assertEqual([(server, None)], args)
1555
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001556 def test_servername(self):
1557 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001558 When a client specifies a server name in its hello message, the
1559 callback passed to :py:obj:`Contexts.set_tlsext_servername_callback` is
1560 invoked and the result of :py:obj:`Connection.get_servername` is that
1561 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001562 """
1563 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001564
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001565 def servername(conn):
1566 args.append((conn, conn.get_servername()))
1567 context = Context(TLSv1_METHOD)
1568 context.set_tlsext_servername_callback(servername)
1569
1570 # Necessary to actually accept the connection
1571 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001572 context.use_certificate(
1573 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001574
1575 # Do a little connection to trigger the logic
1576 server = Connection(context, None)
1577 server.set_accept_state()
1578
1579 client = Connection(Context(TLSv1_METHOD), None)
1580 client.set_connect_state()
1581 client.set_tlsext_host_name(b("foo1.example.com"))
1582
1583 self._interactInMemory(server, client)
1584
1585 self.assertEqual([(server, b("foo1.example.com"))], args)
1586
1587
Cory Benfield84a121e2014-03-31 20:30:25 +01001588class NextProtoNegotiationTests(TestCase, _LoopbackMixin):
1589 """
1590 Test for Next Protocol Negotiation in PyOpenSSL.
1591 """
Cory Benfieldba1820d2015-04-13 17:39:12 -04001592 if _lib.Cryptography_HAS_NEXTPROTONEG:
1593 def test_npn_success(self):
1594 """
1595 Tests that clients and servers that agree on the negotiated next
1596 protocol can correct establish a connection, and that the agreed
1597 protocol is reported by the connections.
1598 """
1599 advertise_args = []
1600 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001601
Cory Benfieldba1820d2015-04-13 17:39:12 -04001602 def advertise(conn):
1603 advertise_args.append((conn,))
1604 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001605
Cory Benfieldba1820d2015-04-13 17:39:12 -04001606 def select(conn, options):
1607 select_args.append((conn, options))
1608 return b'spdy/2'
Cory Benfield84a121e2014-03-31 20:30:25 +01001609
Cory Benfieldba1820d2015-04-13 17:39:12 -04001610 server_context = Context(TLSv1_METHOD)
1611 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001612
Cory Benfieldba1820d2015-04-13 17:39:12 -04001613 client_context = Context(TLSv1_METHOD)
1614 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001615
Cory Benfieldba1820d2015-04-13 17:39:12 -04001616 # Necessary to actually accept the connection
1617 server_context.use_privatekey(
1618 load_privatekey(FILETYPE_PEM, server_key_pem))
1619 server_context.use_certificate(
1620 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001621
Cory Benfieldba1820d2015-04-13 17:39:12 -04001622 # Do a little connection to trigger the logic
1623 server = Connection(server_context, None)
1624 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001625
Cory Benfieldba1820d2015-04-13 17:39:12 -04001626 client = Connection(client_context, None)
1627 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001628
Cory Benfieldba1820d2015-04-13 17:39:12 -04001629 self._interactInMemory(server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001630
Cory Benfieldba1820d2015-04-13 17:39:12 -04001631 self.assertEqual([(server,)], advertise_args)
1632 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001633
Cory Benfieldba1820d2015-04-13 17:39:12 -04001634 self.assertEqual(server.get_next_proto_negotiated(), b'spdy/2')
1635 self.assertEqual(client.get_next_proto_negotiated(), b'spdy/2')
Cory Benfield84a121e2014-03-31 20:30:25 +01001636
Cory Benfieldba1820d2015-04-13 17:39:12 -04001637 def test_npn_client_fail(self):
1638 """
1639 Tests that when clients and servers cannot agree on what protocol
1640 to use next that the TLS connection does not get established.
1641 """
1642 advertise_args = []
1643 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001644
Cory Benfieldba1820d2015-04-13 17:39:12 -04001645 def advertise(conn):
1646 advertise_args.append((conn,))
1647 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001648
Cory Benfieldba1820d2015-04-13 17:39:12 -04001649 def select(conn, options):
1650 select_args.append((conn, options))
1651 return b''
Cory Benfield84a121e2014-03-31 20:30:25 +01001652
Cory Benfieldba1820d2015-04-13 17:39:12 -04001653 server_context = Context(TLSv1_METHOD)
1654 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001655
Cory Benfieldba1820d2015-04-13 17:39:12 -04001656 client_context = Context(TLSv1_METHOD)
1657 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001658
Cory Benfieldba1820d2015-04-13 17:39:12 -04001659 # Necessary to actually accept the connection
1660 server_context.use_privatekey(
1661 load_privatekey(FILETYPE_PEM, server_key_pem))
1662 server_context.use_certificate(
1663 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001664
Cory Benfieldba1820d2015-04-13 17:39:12 -04001665 # Do a little connection to trigger the logic
1666 server = Connection(server_context, None)
1667 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001668
Cory Benfieldba1820d2015-04-13 17:39:12 -04001669 client = Connection(client_context, None)
1670 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001671
Cory Benfieldba1820d2015-04-13 17:39:12 -04001672 # If the client doesn't return anything, the connection will fail.
1673 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001674
Cory Benfieldba1820d2015-04-13 17:39:12 -04001675 self.assertEqual([(server,)], advertise_args)
1676 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001677
Cory Benfieldba1820d2015-04-13 17:39:12 -04001678 def test_npn_select_error(self):
1679 """
1680 Test that we can handle exceptions in the select callback. If
1681 select fails it should be fatal to the connection.
1682 """
1683 advertise_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001684
Cory Benfieldba1820d2015-04-13 17:39:12 -04001685 def advertise(conn):
1686 advertise_args.append((conn,))
1687 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001688
Cory Benfieldba1820d2015-04-13 17:39:12 -04001689 def select(conn, options):
1690 raise TypeError
Cory Benfield0ea76e72015-03-22 09:05:28 +00001691
Cory Benfieldba1820d2015-04-13 17:39:12 -04001692 server_context = Context(TLSv1_METHOD)
1693 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001694
Cory Benfieldba1820d2015-04-13 17:39:12 -04001695 client_context = Context(TLSv1_METHOD)
1696 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001697
Cory Benfieldba1820d2015-04-13 17:39:12 -04001698 # Necessary to actually accept the connection
1699 server_context.use_privatekey(
1700 load_privatekey(FILETYPE_PEM, server_key_pem))
1701 server_context.use_certificate(
1702 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001703
Cory Benfieldba1820d2015-04-13 17:39:12 -04001704 # Do a little connection to trigger the logic
1705 server = Connection(server_context, None)
1706 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001707
Cory Benfieldba1820d2015-04-13 17:39:12 -04001708 client = Connection(client_context, None)
1709 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001710
Cory Benfieldba1820d2015-04-13 17:39:12 -04001711 # If the callback throws an exception it should be raised here.
1712 self.assertRaises(
1713 TypeError, self._interactInMemory, server, client
1714 )
1715 self.assertEqual([(server,)], advertise_args)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001716
Cory Benfieldba1820d2015-04-13 17:39:12 -04001717 def test_npn_advertise_error(self):
1718 """
1719 Test that we can handle exceptions in the advertise callback. If
1720 advertise fails no NPN is advertised to the client.
1721 """
1722 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001723
Cory Benfieldba1820d2015-04-13 17:39:12 -04001724 def advertise(conn):
1725 raise TypeError
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001726
Cory Benfieldba1820d2015-04-13 17:39:12 -04001727 def select(conn, options):
1728 select_args.append((conn, options))
1729 return b''
Cory Benfield0ea76e72015-03-22 09:05:28 +00001730
Cory Benfieldba1820d2015-04-13 17:39:12 -04001731 server_context = Context(TLSv1_METHOD)
1732 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001733
Cory Benfieldba1820d2015-04-13 17:39:12 -04001734 client_context = Context(TLSv1_METHOD)
1735 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001736
Cory Benfieldba1820d2015-04-13 17:39:12 -04001737 # Necessary to actually accept the connection
1738 server_context.use_privatekey(
1739 load_privatekey(FILETYPE_PEM, server_key_pem))
1740 server_context.use_certificate(
1741 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001742
Cory Benfieldba1820d2015-04-13 17:39:12 -04001743 # Do a little connection to trigger the logic
1744 server = Connection(server_context, None)
1745 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001746
Cory Benfieldba1820d2015-04-13 17:39:12 -04001747 client = Connection(client_context, None)
1748 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001749
Cory Benfieldba1820d2015-04-13 17:39:12 -04001750 # If the client doesn't return anything, the connection will fail.
1751 self.assertRaises(
1752 TypeError, self._interactInMemory, server, client
1753 )
1754 self.assertEqual([], select_args)
1755
1756 else:
1757 # No NPN.
1758 def test_npn_not_implemented(self):
1759 # Test the context methods first.
1760 context = Context(TLSv1_METHOD)
1761 fail_methods = [
1762 context.set_npn_advertise_callback,
1763 context.set_npn_select_callback,
1764 ]
1765 for method in fail_methods:
1766 self.assertRaises(
1767 NotImplementedError, method, None
1768 )
1769
1770 # Now test a connection.
1771 conn = Connection(context)
1772 fail_methods = [
1773 conn.get_next_proto_negotiated,
1774 ]
1775 for method in fail_methods:
1776 self.assertRaises(NotImplementedError, method)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001777
1778
Cory Benfield12eae892014-06-07 15:42:56 +01001779class ApplicationLayerProtoNegotiationTests(TestCase, _LoopbackMixin):
1780 """
1781 Tests for ALPN in PyOpenSSL.
1782 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001783 # Skip tests on versions that don't support ALPN.
1784 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001785
Cory Benfielde46fa842015-04-13 16:50:49 -04001786 def test_alpn_success(self):
1787 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001788 Clients and servers that agree on the negotiated ALPN protocol can
1789 correct establish a connection, and the agreed protocol is reported
1790 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001791 """
1792 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001793
Cory Benfielde46fa842015-04-13 16:50:49 -04001794 def select(conn, options):
1795 select_args.append((conn, options))
1796 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001797
Cory Benfielde46fa842015-04-13 16:50:49 -04001798 client_context = Context(TLSv1_METHOD)
1799 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001800
Cory Benfielde46fa842015-04-13 16:50:49 -04001801 server_context = Context(TLSv1_METHOD)
1802 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001803
Cory Benfielde46fa842015-04-13 16:50:49 -04001804 # Necessary to actually accept the connection
1805 server_context.use_privatekey(
1806 load_privatekey(FILETYPE_PEM, server_key_pem))
1807 server_context.use_certificate(
1808 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001809
Cory Benfielde46fa842015-04-13 16:50:49 -04001810 # Do a little connection to trigger the logic
1811 server = Connection(server_context, None)
1812 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001813
Cory Benfielde46fa842015-04-13 16:50:49 -04001814 client = Connection(client_context, None)
1815 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001816
Cory Benfielde46fa842015-04-13 16:50:49 -04001817 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001818
Cory Benfielde46fa842015-04-13 16:50:49 -04001819 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
1820
1821 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1822 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001823
Cory Benfielde46fa842015-04-13 16:50:49 -04001824 def test_alpn_set_on_connection(self):
1825 """
1826 The same as test_alpn_success, but setting the ALPN protocols on
1827 the connection rather than the context.
1828 """
1829 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001830
Cory Benfielde46fa842015-04-13 16:50:49 -04001831 def select(conn, options):
1832 select_args.append((conn, options))
1833 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001834
Cory Benfielde46fa842015-04-13 16:50:49 -04001835 # Setup the client context but don't set any ALPN protocols.
1836 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001837
Cory Benfielde46fa842015-04-13 16:50:49 -04001838 server_context = Context(TLSv1_METHOD)
1839 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001840
Cory Benfielde46fa842015-04-13 16:50:49 -04001841 # Necessary to actually accept the connection
1842 server_context.use_privatekey(
1843 load_privatekey(FILETYPE_PEM, server_key_pem))
1844 server_context.use_certificate(
1845 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001846
Cory Benfielde46fa842015-04-13 16:50:49 -04001847 # Do a little connection to trigger the logic
1848 server = Connection(server_context, None)
1849 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001850
Cory Benfielde46fa842015-04-13 16:50:49 -04001851 # Set the ALPN protocols on the client connection.
1852 client = Connection(client_context, None)
1853 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1854 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001855
Cory Benfielde46fa842015-04-13 16:50:49 -04001856 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001857
Cory Benfielde46fa842015-04-13 16:50:49 -04001858 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001859
Cory Benfielde46fa842015-04-13 16:50:49 -04001860 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1861 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001862
Cory Benfielde46fa842015-04-13 16:50:49 -04001863 def test_alpn_server_fail(self):
1864 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001865 When clients and servers cannot agree on what protocol to use next
1866 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001867 """
1868 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001869
Cory Benfielde46fa842015-04-13 16:50:49 -04001870 def select(conn, options):
1871 select_args.append((conn, options))
1872 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001873
Cory Benfielde46fa842015-04-13 16:50:49 -04001874 client_context = Context(TLSv1_METHOD)
1875 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001876
Cory Benfielde46fa842015-04-13 16:50:49 -04001877 server_context = Context(TLSv1_METHOD)
1878 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001879
Cory Benfielde46fa842015-04-13 16:50:49 -04001880 # Necessary to actually accept the connection
1881 server_context.use_privatekey(
1882 load_privatekey(FILETYPE_PEM, server_key_pem))
1883 server_context.use_certificate(
1884 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001885
Cory Benfielde46fa842015-04-13 16:50:49 -04001886 # Do a little connection to trigger the logic
1887 server = Connection(server_context, None)
1888 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001889
Cory Benfielde46fa842015-04-13 16:50:49 -04001890 client = Connection(client_context, None)
1891 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001892
Cory Benfielde46fa842015-04-13 16:50:49 -04001893 # If the client doesn't return anything, the connection will fail.
1894 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001895
Cory Benfielde46fa842015-04-13 16:50:49 -04001896 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001897
Cory Benfielde46fa842015-04-13 16:50:49 -04001898 def test_alpn_no_server(self):
1899 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001900 When clients and servers cannot agree on what protocol to use next
1901 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04001902 """
1903 client_context = Context(TLSv1_METHOD)
1904 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04001905
Cory Benfielde46fa842015-04-13 16:50:49 -04001906 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04001907
Cory Benfielde46fa842015-04-13 16:50:49 -04001908 # Necessary to actually accept the connection
1909 server_context.use_privatekey(
1910 load_privatekey(FILETYPE_PEM, server_key_pem))
1911 server_context.use_certificate(
1912 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04001913
Cory Benfielde46fa842015-04-13 16:50:49 -04001914 # Do a little connection to trigger the logic
1915 server = Connection(server_context, None)
1916 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001917
Cory Benfielde46fa842015-04-13 16:50:49 -04001918 client = Connection(client_context, None)
1919 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001920
Cory Benfielde46fa842015-04-13 16:50:49 -04001921 # Do the dance.
1922 self._interactInMemory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04001923
Cory Benfielde46fa842015-04-13 16:50:49 -04001924 self.assertEqual(client.get_alpn_proto_negotiated(), b'')
Cory Benfielde3d57152015-04-11 17:57:35 -04001925
Cory Benfielde46fa842015-04-13 16:50:49 -04001926 def test_alpn_callback_exception(self):
1927 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001928 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04001929 """
1930 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001931
Cory Benfielde46fa842015-04-13 16:50:49 -04001932 def select(conn, options):
1933 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04001934 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001935
Cory Benfielde46fa842015-04-13 16:50:49 -04001936 client_context = Context(TLSv1_METHOD)
1937 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04001938
Cory Benfielde46fa842015-04-13 16:50:49 -04001939 server_context = Context(TLSv1_METHOD)
1940 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04001941
Cory Benfielde46fa842015-04-13 16:50:49 -04001942 # Necessary to actually accept the connection
1943 server_context.use_privatekey(
1944 load_privatekey(FILETYPE_PEM, server_key_pem))
1945 server_context.use_certificate(
1946 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04001947
Cory Benfielde46fa842015-04-13 16:50:49 -04001948 # Do a little connection to trigger the logic
1949 server = Connection(server_context, None)
1950 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001951
Cory Benfielde46fa842015-04-13 16:50:49 -04001952 client = Connection(client_context, None)
1953 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001954
Cory Benfielde46fa842015-04-13 16:50:49 -04001955 self.assertRaises(
1956 TypeError, self._interactInMemory, server, client
1957 )
1958 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfieldf1177e72015-04-12 09:11:49 -04001959
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001960 else:
1961 # No ALPN.
1962 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04001963 """
1964 If ALPN is not in OpenSSL, we should raise NotImplementedError.
1965 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001966 # Test the context methods first.
1967 context = Context(TLSv1_METHOD)
Cory Benfield307e9e62015-04-13 18:21:12 -04001968 self.assertRaises(
1969 NotImplementedError, context.set_alpn_protos, None
1970 )
1971 self.assertRaises(
1972 NotImplementedError, context.set_alpn_select_callback, None
1973 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001974
1975 # Now test a connection.
1976 conn = Connection(context)
Cory Benfield307e9e62015-04-13 18:21:12 -04001977 self.assertRaises(
Alex Gaynor68417232015-09-04 07:56:29 -04001978 NotImplementedError, conn.set_alpn_protos, None
Cory Benfield307e9e62015-04-13 18:21:12 -04001979 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001980
Cory Benfieldf1177e72015-04-12 09:11:49 -04001981
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001982class SessionTests(TestCase):
1983 """
1984 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1985 """
1986 def test_construction(self):
1987 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001988 :py:class:`Session` can be constructed with no arguments, creating
1989 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001990 """
1991 new_session = Session()
1992 self.assertTrue(isinstance(new_session, Session))
1993
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001994 def test_construction_wrong_args(self):
1995 """
1996 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
1997 is raised.
1998 """
1999 self.assertRaises(TypeError, Session, 123)
2000 self.assertRaises(TypeError, Session, "hello")
2001 self.assertRaises(TypeError, Session, object())
2002
2003
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002004class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05002005 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002006 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002007 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002008 # XXX get_peer_certificate -> None
2009 # XXX sock_shutdown
2010 # XXX master_key -> TypeError
2011 # XXX server_random -> TypeError
2012 # XXX state_string
2013 # XXX connect -> TypeError
2014 # XXX connect_ex -> TypeError
2015 # XXX set_connect_state -> TypeError
2016 # XXX set_accept_state -> TypeError
2017 # XXX renegotiate_pending
2018 # XXX do_handshake -> TypeError
2019 # XXX bio_read -> TypeError
2020 # XXX recv -> TypeError
2021 # XXX send -> TypeError
2022 # XXX bio_write -> TypeError
2023
Rick Deane15b1472009-07-09 15:53:42 -05002024 def test_type(self):
2025 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002026 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same
2027 type object and can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002028 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002029 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05002030 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002031 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002032
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002033 def test_get_context(self):
2034 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002035 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance
2036 used to construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002037 """
2038 context = Context(TLSv1_METHOD)
2039 connection = Connection(context, None)
2040 self.assertIdentical(connection.get_context(), context)
2041
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002042 def test_get_context_wrong_args(self):
2043 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002044 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called
2045 with any arguments.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002046 """
2047 connection = Connection(Context(TLSv1_METHOD), None)
2048 self.assertRaises(TypeError, connection.get_context, None)
2049
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002050 def test_set_context_wrong_args(self):
2051 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002052 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called
2053 with a non-:py:obj:`Context` instance argument or with any number of
2054 arguments other than 1.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002055 """
2056 ctx = Context(TLSv1_METHOD)
2057 connection = Connection(ctx, None)
2058 self.assertRaises(TypeError, connection.set_context)
2059 self.assertRaises(TypeError, connection.set_context, object())
2060 self.assertRaises(TypeError, connection.set_context, "hello")
2061 self.assertRaises(TypeError, connection.set_context, 1)
2062 self.assertRaises(TypeError, connection.set_context, 1, 2)
2063 self.assertRaises(
2064 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
2065 self.assertIdentical(ctx, connection.get_context())
2066
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002067 def test_set_context(self):
2068 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002069 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context`
2070 instance to be used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002071 """
2072 original = Context(SSLv23_METHOD)
2073 replacement = Context(TLSv1_METHOD)
2074 connection = Connection(original, None)
2075 connection.set_context(replacement)
2076 self.assertIdentical(replacement, connection.get_context())
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002077 # Lose our references to the contexts, just in case the Connection
2078 # isn't properly managing its own contributions to their reference
2079 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002080 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002081 collect()
2082
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002083 def test_set_tlsext_host_name_wrong_args(self):
2084 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002085 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte
2086 string argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09002087 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002088 """
2089 conn = Connection(Context(TLSv1_METHOD), None)
2090 self.assertRaises(TypeError, conn.set_tlsext_host_name)
2091 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
2092 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
2093 self.assertRaises(
2094 TypeError, conn.set_tlsext_host_name, b("with\0null"))
2095
Abraham Martinc5484ba2015-03-25 15:33:05 +00002096 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002097 # On Python 3.x, don't accidentally implicitly convert from text.
2098 self.assertRaises(
2099 TypeError,
2100 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002101
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002102 def test_get_servername_wrong_args(self):
2103 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002104 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if
2105 called with any arguments.
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002106 """
2107 connection = Connection(Context(TLSv1_METHOD), None)
2108 self.assertRaises(TypeError, connection.get_servername, object())
2109 self.assertRaises(TypeError, connection.get_servername, 1)
2110 self.assertRaises(TypeError, connection.get_servername, "hello")
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
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002120 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002121 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002122 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with
2123 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
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002128 def test_peek(self):
2129 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002130 :py:obj:`Connection.recv` peeks into the connection if
2131 :py:obj:`socket.MSG_PEEK` is passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002132 """
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
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002139 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002140 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002141 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with
2142 a non-address argument or with the wrong number of arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002143 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002144 connection = Connection(Context(TLSv1_METHOD), socket())
2145 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002146 self.assertRaises(TypeError, connection.connect)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002147 self.assertRaises(
2148 TypeError, connection.connect, ("127.0.0.1", 1), None
2149 )
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002150
kjavfe508d62015-09-02 12:20:35 +01002151 def test_connection_undefined_attr(self):
2152 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002153 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with
2154 a non-address argument or with the wrong number of arguments.
kjavfe508d62015-09-02 12:20:35 +01002155 """
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002156
kjavfe508d62015-09-02 12:20:35 +01002157 def attr_access_test(connection):
2158 return connection.an_attribute_which_is_not_defined
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002159
kjavfe508d62015-09-02 12:20:35 +01002160 connection = Connection(Context(TLSv1_METHOD), None)
2161 self.assertRaises(AttributeError, attr_access_test, connection)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002162
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002163 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002164 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002165 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the
2166 underlying socket connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002167 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002168 client = socket()
2169 context = Context(TLSv1_METHOD)
2170 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002171 # pytest.raises here doesn't work because of a bug in py.test on Python
2172 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002173 try:
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002174 clientSSL.connect(("127.0.0.1", 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002175 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002176 exc = e
2177 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002178
2179 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002180 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002181 :py:obj:`Connection.connect` establishes a connection to the specified
2182 address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002183 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002184 port = socket()
2185 port.bind(('', 0))
2186 port.listen(3)
2187
2188 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002189 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2190 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002191
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002192 @pytest.mark.skipif(
2193 platform == "darwin",
2194 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2195 )
2196 def test_connect_ex(self):
2197 """
2198 If there is a connection error, :py:obj:`Connection.connect_ex`
2199 returns the errno instead of raising an exception.
2200 """
2201 port = socket()
2202 port.bind(('', 0))
2203 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002204
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002205 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2206 clientSSL.setblocking(False)
2207 result = clientSSL.connect_ex(port.getsockname())
2208 expected = (EINPROGRESS, EWOULDBLOCK)
2209 self.assertTrue(
2210 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002211
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002212 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002213 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002214 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with
2215 any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002216 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002217 connection = Connection(Context(TLSv1_METHOD), socket())
2218 self.assertRaises(TypeError, connection.accept, None)
2219
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002220 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002221 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002222 :py:obj:`Connection.accept` accepts a pending connection attempt and
2223 returns a tuple of a new :py:obj:`Connection` (the accepted client) and
2224 the address the connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002225 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002226 ctx = Context(TLSv1_METHOD)
2227 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2228 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002229 port = socket()
2230 portSSL = Connection(ctx, port)
2231 portSSL.bind(('', 0))
2232 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002233
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002234 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002235
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002236 # Calling portSSL.getsockname() here to get the server IP address
2237 # sounds great, but frequently fails on Windows.
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002238 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002239
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002240 serverSSL, address = portSSL.accept()
2241
2242 self.assertTrue(isinstance(serverSSL, Connection))
2243 self.assertIdentical(serverSSL.get_context(), ctx)
2244 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002245
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002246 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002247 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002248 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with
2249 the wrong number of arguments or with arguments other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002250 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002251 connection = Connection(Context(TLSv1_METHOD), None)
2252 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04002253 self.assertRaises(TypeError, connection.get_shutdown, None)
2254 self.assertRaises(TypeError, connection.set_shutdown)
2255 self.assertRaises(TypeError, connection.set_shutdown, None)
2256 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002257
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002258 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002259 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002260 :py:obj:`Connection.shutdown` performs an SSL-level connection
2261 shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002262 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002263 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002264 self.assertFalse(server.shutdown())
2265 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002266 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002267 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
2268 client.shutdown()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002269 self.assertEquals(
2270 client.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN
2271 )
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002272 self.assertRaises(ZeroReturnError, server.recv, 1024)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002273 self.assertEquals(
2274 server.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN
2275 )
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002276
Paul Aurichc85e0862015-01-08 08:34:33 -08002277 def test_shutdown_closed(self):
2278 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002279 If the underlying socket is closed, :py:obj:`Connection.shutdown`
2280 propagates the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002281 """
2282 server, client = self._loopback()
2283 server.sock_shutdown(2)
2284 exc = self.assertRaises(SysCallError, server.shutdown)
2285 if platform == "win32":
2286 self.assertEqual(exc.args[0], ESHUTDOWN)
2287 else:
2288 self.assertEqual(exc.args[0], EPIPE)
2289
Glyph89389472015-04-14 17:29:26 -04002290 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002291 """
Glyph89389472015-04-14 17:29:26 -04002292 If the underlying connection is truncated, :obj:`Connection.shutdown`
2293 raises an :obj:`Error`.
Glyph6064ec32015-04-14 16:38:22 -04002294 """
Glyph89389472015-04-14 17:29:26 -04002295 server_ctx = Context(TLSv1_METHOD)
2296 client_ctx = Context(TLSv1_METHOD)
2297 server_ctx.use_privatekey(
2298 load_privatekey(FILETYPE_PEM, server_key_pem))
2299 server_ctx.use_certificate(
2300 load_certificate(FILETYPE_PEM, server_cert_pem))
2301 server = Connection(server_ctx, None)
2302 client = Connection(client_ctx, None)
2303 self._handshakeInMemory(client, server)
2304 self.assertEqual(server.shutdown(), False)
2305 self.assertRaises(WantReadError, server.shutdown)
2306 server.bio_shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002307 self.assertRaises(Error, server.shutdown)
2308
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002309 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002310 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002311 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection
2312 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002313 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002314 connection = Connection(Context(TLSv1_METHOD), socket())
2315 connection.set_shutdown(RECEIVED_SHUTDOWN)
2316 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2317
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002318 @skip_if_py3
2319 def test_set_shutdown_long(self):
2320 """
2321 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
2322 of type :py:obj:`long` as well as :py:obj:`int`.
2323 """
2324 connection = Connection(Context(TLSv1_METHOD), socket())
2325 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
2326 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002327
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002328 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002329 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002330 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called
2331 with other than one argument. :py:obj:`Connection.get_app_data` raises
2332 :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002333 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002334 conn = Connection(Context(TLSv1_METHOD), None)
2335 self.assertRaises(TypeError, conn.get_app_data, None)
2336 self.assertRaises(TypeError, conn.set_app_data)
2337 self.assertRaises(TypeError, conn.set_app_data, None, None)
2338
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002339 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002340 """
2341 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002342 :py:obj:`Connection.set_app_data` and later retrieved with
2343 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002344 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002345 conn = Connection(Context(TLSv1_METHOD), None)
2346 app_data = object()
2347 conn.set_app_data(app_data)
2348 self.assertIdentical(conn.get_app_data(), app_data)
2349
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002350 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002351 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002352 :py:obj:`Connection.makefile` is not implemented and calling that
2353 method raises :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002354 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002355 conn = Connection(Context(TLSv1_METHOD), None)
2356 self.assertRaises(NotImplementedError, conn.makefile)
2357
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002358 def test_get_peer_cert_chain_wrong_args(self):
2359 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002360 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if
2361 called with any arguments.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002362 """
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
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002369 def test_get_peer_cert_chain(self):
2370 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002371 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates
2372 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002373 """
2374 chain = _create_certificate_chain()
2375 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2376
2377 serverContext = Context(TLSv1_METHOD)
2378 serverContext.use_privatekey(skey)
2379 serverContext.use_certificate(scert)
2380 serverContext.add_extra_chain_cert(icert)
2381 serverContext.add_extra_chain_cert(cacert)
2382 server = Connection(serverContext, None)
2383 server.set_accept_state()
2384
2385 # Create the client
2386 clientContext = Context(TLSv1_METHOD)
2387 clientContext.set_verify(VERIFY_NONE, verify_cb)
2388 client = Connection(clientContext, None)
2389 client.set_connect_state()
2390
2391 self._interactInMemory(client, server)
2392
2393 chain = client.get_peer_cert_chain()
2394 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002395 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002396 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002397 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002398 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002399 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002400 "Authority Certificate", chain[2].get_subject().CN)
2401
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002402 def test_get_peer_cert_chain_none(self):
2403 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002404 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the
2405 peer sends no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002406 """
2407 ctx = Context(TLSv1_METHOD)
2408 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2409 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2410 server = Connection(ctx, None)
2411 server.set_accept_state()
2412 client = Connection(Context(TLSv1_METHOD), None)
2413 client.set_connect_state()
2414 self._interactInMemory(client, server)
2415 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002416
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002417 def test_get_session_wrong_args(self):
2418 """
2419 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
2420 with any arguments.
2421 """
2422 ctx = Context(TLSv1_METHOD)
2423 server = Connection(ctx, None)
2424 self.assertRaises(TypeError, server.get_session, 123)
2425 self.assertRaises(TypeError, server.get_session, "hello")
2426 self.assertRaises(TypeError, server.get_session, object())
2427
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002428 def test_get_session_unconnected(self):
2429 """
2430 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
2431 an object which has not been connected.
2432 """
2433 ctx = Context(TLSv1_METHOD)
2434 server = Connection(ctx, None)
2435 session = server.get_session()
2436 self.assertIdentical(None, session)
2437
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002438 def test_server_get_session(self):
2439 """
2440 On the server side of a connection, :py:obj:`Connection.get_session`
2441 returns a :py:class:`Session` instance representing the SSL session for
2442 that connection.
2443 """
2444 server, client = self._loopback()
2445 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002446 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002447
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002448 def test_client_get_session(self):
2449 """
2450 On the client side of a connection, :py:obj:`Connection.get_session`
2451 returns a :py:class:`Session` instance representing the SSL session for
2452 that connection.
2453 """
2454 server, client = self._loopback()
2455 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002456 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002457
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002458 def test_set_session_wrong_args(self):
2459 """
2460 If called with an object that is not an instance of :py:class:`Session`,
2461 or with other than one argument, :py:obj:`Connection.set_session` raises
2462 :py:obj:`TypeError`.
2463 """
2464 ctx = Context(TLSv1_METHOD)
2465 connection = Connection(ctx, None)
2466 self.assertRaises(TypeError, connection.set_session)
2467 self.assertRaises(TypeError, connection.set_session, 123)
2468 self.assertRaises(TypeError, connection.set_session, "hello")
2469 self.assertRaises(TypeError, connection.set_session, object())
2470 self.assertRaises(
2471 TypeError, connection.set_session, Session(), Session())
2472
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002473 def test_client_set_session(self):
2474 """
2475 :py:obj:`Connection.set_session`, when used prior to a connection being
2476 established, accepts a :py:class:`Session` instance and causes an
2477 attempt to re-use the session it represents when the SSL handshake is
2478 performed.
2479 """
2480 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2481 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2482 ctx = Context(TLSv1_METHOD)
2483 ctx.use_privatekey(key)
2484 ctx.use_certificate(cert)
2485 ctx.set_session_id("unity-test")
2486
2487 def makeServer(socket):
2488 server = Connection(ctx, socket)
2489 server.set_accept_state()
2490 return server
2491
2492 originalServer, originalClient = self._loopback(
2493 serverFactory=makeServer)
2494 originalSession = originalClient.get_session()
2495
2496 def makeClient(socket):
2497 client = self._loopbackClientFactory(socket)
2498 client.set_session(originalSession)
2499 return client
2500 resumedServer, resumedClient = self._loopback(
2501 serverFactory=makeServer,
2502 clientFactory=makeClient)
2503
2504 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002505 # identifier for the session (new enough versions of OpenSSL expose
2506 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002507 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002508 # session is re-used. As long as the master key for the two
2509 # connections is the same, the session was re-used!
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002510 self.assertEqual(
2511 originalServer.master_key(), resumedServer.master_key())
2512
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002513 def test_set_session_wrong_method(self):
2514 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002515 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002516 instance associated with a context using a different SSL method than
2517 the :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002518 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002519 """
2520 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2521 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2522 ctx = Context(TLSv1_METHOD)
2523 ctx.use_privatekey(key)
2524 ctx.use_certificate(cert)
2525 ctx.set_session_id("unity-test")
2526
2527 def makeServer(socket):
2528 server = Connection(ctx, socket)
2529 server.set_accept_state()
2530 return server
2531
2532 originalServer, originalClient = self._loopback(
2533 serverFactory=makeServer)
2534 originalSession = originalClient.get_session()
2535
2536 def makeClient(socket):
2537 # Intentionally use a different, incompatible method here.
2538 client = Connection(Context(SSLv3_METHOD), socket)
2539 client.set_connect_state()
2540 client.set_session(originalSession)
2541 return client
2542
2543 self.assertRaises(
2544 Error,
2545 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2546
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002547 def test_wantWriteError(self):
2548 """
2549 :py:obj:`Connection` methods which generate output raise
2550 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2551 fail indicating a should-write state.
2552 """
2553 client_socket, server_socket = socket_pair()
2554 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002555 # anything. Only write a single byte at a time so we can be sure we
2556 # completely fill the buffer. Even though the socket API is allowed to
2557 # signal a short write via its return value it seems this doesn't
2558 # always happen on all platforms (FreeBSD and OS X particular) for the
2559 # very last bit of available buffer space.
2560 msg = b"x"
2561 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002562 try:
2563 client_socket.send(msg)
2564 except error as e:
2565 if e.errno == EWOULDBLOCK:
2566 break
2567 raise
2568 else:
2569 self.fail(
2570 "Failed to fill socket buffer, cannot test BIO want write")
2571
2572 ctx = Context(TLSv1_METHOD)
2573 conn = Connection(ctx, client_socket)
2574 # Client's speak first, so make it an SSL client
2575 conn.set_connect_state()
2576 self.assertRaises(WantWriteError, conn.do_handshake)
2577
2578 # XXX want_read
2579
Fedor Brunner416f4a12014-03-28 13:18:38 +01002580 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002581 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002582 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2583 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002584 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002585 ctx = Context(TLSv1_METHOD)
2586 connection = Connection(ctx, None)
2587 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002588
2589 def test_get_peer_finished_before_connect(self):
2590 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002591 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2592 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002593 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002594 ctx = Context(TLSv1_METHOD)
2595 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002596 self.assertEqual(connection.get_peer_finished(), None)
2597
Fedor Brunner416f4a12014-03-28 13:18:38 +01002598 def test_get_finished(self):
2599 """
2600 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002601 message send from client, or server. Finished messages are send during
2602 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002603 """
2604
Fedor Brunner5747b932014-03-05 14:22:34 +01002605 server, client = self._loopback()
2606
2607 self.assertNotEqual(server.get_finished(), None)
2608 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002609
2610 def test_get_peer_finished(self):
2611 """
2612 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002613 message received from client, or server. Finished messages are send
2614 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002615 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002616 server, client = self._loopback()
2617
2618 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002619 self.assertTrue(len(server.get_peer_finished()) > 0)
2620
Fedor Brunner416f4a12014-03-28 13:18:38 +01002621 def test_tls_finished_message_symmetry(self):
2622 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002623 The TLS Finished message send by server must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002624 received by client.
2625
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002626 The TLS Finished message send by client must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002627 received by server.
2628 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002629 server, client = self._loopback()
2630
Fedor Brunner5747b932014-03-05 14:22:34 +01002631 self.assertEqual(server.get_finished(), client.get_peer_finished())
2632 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002633
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002634 def test_get_cipher_name_before_connect(self):
2635 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002636 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2637 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002638 """
2639 ctx = Context(TLSv1_METHOD)
2640 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002641 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002642
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002643 def test_get_cipher_name(self):
2644 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002645 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2646 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002647 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002648 server, client = self._loopback()
2649 server_cipher_name, client_cipher_name = \
2650 server.get_cipher_name(), client.get_cipher_name()
2651
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002652 self.assertIsInstance(server_cipher_name, text_type)
2653 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002654
2655 self.assertEqual(server_cipher_name, client_cipher_name)
2656
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002657 def test_get_cipher_version_before_connect(self):
2658 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002659 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2660 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002661 """
2662 ctx = Context(TLSv1_METHOD)
2663 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002664 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002665
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002666 def test_get_cipher_version(self):
2667 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002668 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2669 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002670 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002671 server, client = self._loopback()
2672 server_cipher_version, client_cipher_version = \
2673 server.get_cipher_version(), client.get_cipher_version()
2674
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002675 self.assertIsInstance(server_cipher_version, text_type)
2676 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002677
2678 self.assertEqual(server_cipher_version, client_cipher_version)
2679
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002680 def test_get_cipher_bits_before_connect(self):
2681 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002682 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2683 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002684 """
2685 ctx = Context(TLSv1_METHOD)
2686 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002687 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002688
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002689 def test_get_cipher_bits(self):
2690 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002691 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2692 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002693 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002694 server, client = self._loopback()
2695 server_cipher_bits, client_cipher_bits = \
2696 server.get_cipher_bits(), client.get_cipher_bits()
2697
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002698 self.assertIsInstance(server_cipher_bits, int)
2699 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002700
2701 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002702
Jim Shaverabff1882015-05-27 09:15:55 -04002703 def test_get_protocol_version_name(self):
2704 """
2705 :py:obj:`Connection.get_protocol_version_name()` returns a string
2706 giving the protocol version of the current connection.
2707 """
2708 server, client = self._loopback()
2709 client_protocol_version_name = client.get_protocol_version_name()
2710 server_protocol_version_name = server.get_protocol_version_name()
2711
Jim Shaver58d25732015-05-28 11:52:32 -04002712 self.assertIsInstance(server_protocol_version_name, text_type)
2713 self.assertIsInstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002714
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002715 self.assertEqual(
2716 server_protocol_version_name, client_protocol_version_name
2717 )
Jim Shaverabff1882015-05-27 09:15:55 -04002718
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002719 def test_get_protocol_version(self):
2720 """
Alex Gaynor43307782015-09-04 09:05:45 -04002721 :py:obj:`Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002722 giving the protocol version of the current connection.
2723 """
2724 server, client = self._loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002725 client_protocol_version = client.get_protocol_version()
2726 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002727
Jim Shaverabff1882015-05-27 09:15:55 -04002728 self.assertIsInstance(server_protocol_version, int)
2729 self.assertIsInstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002730
2731 self.assertEqual(server_protocol_version, client_protocol_version)
2732
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002733
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002734class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002735 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002736 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002737 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002738 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002739 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002740 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002741 arguments.
2742 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002743 connection = Connection(Context(TLSv1_METHOD), None)
2744 self.assertRaises(TypeError, connection.get_cipher_list, None)
2745
2746
2747 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002748 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002749 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2750 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002751 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002752 connection = Connection(Context(TLSv1_METHOD), None)
2753 ciphers = connection.get_cipher_list()
2754 self.assertTrue(isinstance(ciphers, list))
2755 for cipher in ciphers:
2756 self.assertTrue(isinstance(cipher, str))
2757
2758
2759
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002760class ConnectionSendTests(TestCase, _LoopbackMixin):
2761 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002762 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002763 """
2764 def test_wrong_args(self):
2765 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002766 When called with arguments other than string argument for its first
2767 parameter or more than two arguments, :py:obj:`Connection.send` raises
2768 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002769 """
2770 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002771 self.assertRaises(TypeError, connection.send)
2772 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002773 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002774
2775
2776 def test_short_bytes(self):
2777 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002778 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002779 and returns the number of bytes sent.
2780 """
2781 server, client = self._loopback()
2782 count = server.send(b('xy'))
2783 self.assertEquals(count, 2)
2784 self.assertEquals(client.recv(2), b('xy'))
2785
Abraham Martinef063482015-03-25 14:06:24 +00002786
2787 def test_text(self):
2788 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002789 When passed a text, :py:obj:`Connection.send` transmits all of it and
2790 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002791 """
2792 server, client = self._loopback()
2793 with catch_warnings(record=True) as w:
2794 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002795 count = server.send(b"xy".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002796 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002797 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002798 WARNING_TYPE_EXPECTED
2799 ),
2800 str(w[-1].message)
2801 )
2802 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinef063482015-03-25 14:06:24 +00002803 self.assertEquals(count, 2)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002804 self.assertEquals(client.recv(2), b"xy")
Abraham Martinef063482015-03-25 14:06:24 +00002805
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002806 try:
2807 memoryview
2808 except NameError:
2809 "cannot test sending memoryview without memoryview"
2810 else:
2811 def test_short_memoryview(self):
2812 """
2813 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002814 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002815 bytes sent.
2816 """
2817 server, client = self._loopback()
2818 count = server.send(memoryview(b('xy')))
2819 self.assertEquals(count, 2)
2820 self.assertEquals(client.recv(2), b('xy'))
2821
2822
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002823 try:
2824 buffer
2825 except NameError:
2826 "cannot test sending buffer without buffer"
2827 else:
2828 def test_short_buffer(self):
2829 """
2830 When passed a buffer containing a small number of bytes,
2831 :py:obj:`Connection.send` transmits all of them and returns the number of
2832 bytes sent.
2833 """
2834 server, client = self._loopback()
2835 count = server.send(buffer(b('xy')))
2836 self.assertEquals(count, 2)
2837 self.assertEquals(client.recv(2), b('xy'))
2838
2839
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002840
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002841def _make_memoryview(size):
2842 """
2843 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2844 size.
2845 """
2846 return memoryview(bytearray(size))
2847
2848
2849
Cory Benfield62d10332014-06-15 10:03:41 +01002850class ConnectionRecvIntoTests(TestCase, _LoopbackMixin):
2851 """
2852 Tests for :py:obj:`Connection.recv_into`
2853 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002854 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002855 """
2856 Assert that when the given buffer is passed to
2857 ``Connection.recv_into``, whatever bytes are available to be received
2858 that fit into that buffer are written into that buffer.
2859 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002860 output_buffer = factory(5)
2861
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002862 server, client = self._loopback()
2863 server.send(b('xy'))
2864
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002865 self.assertEqual(client.recv_into(output_buffer), 2)
2866 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002867
2868
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002869 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002870 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002871 :py:obj:`Connection.recv_into` can be passed a ``bytearray`` instance
2872 and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002873 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002874 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002875
2876
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002877 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002878 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002879 Assert that when the given buffer is passed to ``Connection.recv_into``
2880 along with a value for ``nbytes`` that is less than the size of that
2881 buffer, only ``nbytes`` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002882 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002883 output_buffer = factory(10)
2884
Cory Benfield62d10332014-06-15 10:03:41 +01002885 server, client = self._loopback()
2886 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002887
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002888 self.assertEqual(client.recv_into(output_buffer, 5), 5)
2889 self.assertEqual(
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002890 output_buffer, bytearray(b('abcde\x00\x00\x00\x00\x00'))
2891 )
2892
2893
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002894 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002895 """
2896 When called with a ``bytearray`` instance,
2897 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter and
2898 doesn't copy in more than that number of bytes.
2899 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002900 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002901
2902
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002903 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002904 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002905 Assert that if there are more bytes available to be read from the
2906 receive buffer than would fit into the buffer passed to
2907 :py:obj:`Connection.recv_into`, only as many as fit are written into
2908 it.
Cory Benfield62d10332014-06-15 10:03:41 +01002909 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002910 output_buffer = factory(5)
2911
Cory Benfield62d10332014-06-15 10:03:41 +01002912 server, client = self._loopback()
2913 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002914
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002915 self.assertEqual(client.recv_into(output_buffer), 5)
2916 self.assertEqual(output_buffer, bytearray(b('abcde')))
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002917 rest = client.recv(5)
2918 self.assertEqual(b('fghij'), rest)
2919
2920
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002921 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002922 """
2923 When called with a ``bytearray`` instance,
2924 :py:obj:`Connection.recv_into` respects the size of the array and
2925 doesn't write more bytes into it than will fit.
2926 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002927 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002928
2929
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002930 def _really_doesnt_overfill_test(self, factory):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002931 """
2932 Assert that if the value given by ``nbytes`` is greater than the actual
2933 size of the output buffer passed to :py:obj:`Connection.recv_into`, the
2934 behavior is as if no value was given for ``nbytes`` at all.
2935 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002936 output_buffer = factory(5)
2937
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002938 server, client = self._loopback()
2939 server.send(b('abcdefghij'))
2940
2941 self.assertEqual(client.recv_into(output_buffer, 50), 5)
2942 self.assertEqual(output_buffer, bytearray(b('abcde')))
2943 rest = client.recv(5)
2944 self.assertEqual(b('fghij'), rest)
2945
2946
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002947 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002948 """
2949 When called with a ``bytearray`` instance and an ``nbytes`` value that
2950 is too large, :py:obj:`Connection.recv_into` respects the size of the
2951 array and not the ``nbytes`` value and doesn't write more bytes into
2952 the buffer than will fit.
2953 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002954 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002955
2956
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002957 def test_peek(self):
2958
2959 server, client = self._loopback()
2960 server.send(b('xy'))
2961
2962 for _ in range(2):
2963 output_buffer = bytearray(5)
2964 self.assertEqual(client.recv_into(output_buffer, flags=MSG_PEEK), 2)
2965 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
2966
2967
Cory Benfield62d10332014-06-15 10:03:41 +01002968 try:
2969 memoryview
2970 except NameError:
2971 "cannot test recv_into memoryview without memoryview"
2972 else:
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002973 def test_memoryview_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002974 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002975 :py:obj:`Connection.recv_into` can be passed a ``memoryview``
2976 instance and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002977 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002978 self._no_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002979
2980
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002981 def test_memoryview_respects_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002982 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002983 When called with a ``memoryview`` instance,
2984 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter
2985 and doesn't copy more than that number of bytes in.
Cory Benfield62d10332014-06-15 10:03:41 +01002986 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002987 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002988
2989
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002990 def test_memoryview_doesnt_overfill(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002991 """
Jean-Paul Calderone8fd82552015-03-15 17:21:07 -04002992 When called with a ``memoryview`` instance,
2993 :py:obj:`Connection.recv_into` respects the size of the array and
2994 doesn't write more bytes into it than will fit.
Cory Benfield62d10332014-06-15 10:03:41 +01002995 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002996 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002997
2998
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002999 def test_memoryview_really_doesnt_overfill(self):
3000 """
3001 When called with a ``memoryview`` instance and an ``nbytes`` value
3002 that is too large, :py:obj:`Connection.recv_into` respects the size
3003 of the array and not the ``nbytes`` value and doesn't write more
3004 bytes into the buffer than will fit.
3005 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003006 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003007
3008
Cory Benfield62d10332014-06-15 10:03:41 +01003009
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003010class ConnectionSendallTests(TestCase, _LoopbackMixin):
3011 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003012 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003013 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003014 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003015 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003016 When called with arguments other than a string argument for its first
3017 parameter or with more than two arguments, :py:obj:`Connection.sendall`
3018 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003019 """
3020 connection = Connection(Context(TLSv1_METHOD), None)
3021 self.assertRaises(TypeError, connection.sendall)
3022 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003023 self.assertRaises(
3024 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003025
3026
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003027 def test_short(self):
3028 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003029 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003030 it.
3031 """
3032 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04003033 server.sendall(b('x'))
3034 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003035
3036
Abraham Martinef063482015-03-25 14:06:24 +00003037 def test_text(self):
3038 """
Jean-Paul Calderone93477422015-04-13 20:38:57 -04003039 :py:obj:`Connection.sendall` transmits all the content in the string
3040 passed to it raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003041 """
3042 server, client = self._loopback()
3043 with catch_warnings(record=True) as w:
3044 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003045 server.sendall(b"x".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003046 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003047 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003048 WARNING_TYPE_EXPECTED
3049 ),
3050 str(w[-1].message)
3051 )
3052 self.assertIs(w[-1].category, DeprecationWarning)
3053 self.assertEquals(client.recv(1), b"x")
Abraham Martinef063482015-03-25 14:06:24 +00003054
3055
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003056 try:
3057 memoryview
3058 except NameError:
3059 "cannot test sending memoryview without memoryview"
3060 else:
3061 def test_short_memoryview(self):
3062 """
3063 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003064 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003065 """
3066 server, client = self._loopback()
3067 server.sendall(memoryview(b('x')))
3068 self.assertEquals(client.recv(1), b('x'))
3069
3070
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003071 try:
3072 buffer
3073 except NameError:
3074 "cannot test sending buffers without buffers"
3075 else:
3076 def test_short_buffers(self):
3077 """
3078 When passed a buffer containing a small number of bytes,
3079 :py:obj:`Connection.sendall` transmits all of them.
3080 """
3081 server, client = self._loopback()
3082 server.sendall(buffer(b('x')))
3083 self.assertEquals(client.recv(1), b('x'))
3084
3085
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003086 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003087 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003088 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003089 it even if this requires multiple calls of an underlying write function.
3090 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003091 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003092 # Should be enough, underlying SSL_write should only do 16k at a time.
3093 # On Windows, after 32k of bytes the write will block (forever - because
3094 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04003095 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003096 server.sendall(message)
3097 accum = []
3098 received = 0
3099 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003100 data = client.recv(1024)
3101 accum.append(data)
3102 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04003103 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003104
3105
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003106 def test_closed(self):
3107 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003108 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003109 write error from the low level write call.
3110 """
3111 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003112 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003113 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003114 if platform == "win32":
3115 self.assertEqual(exc.args[0], ESHUTDOWN)
3116 else:
3117 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003118
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003119
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04003120
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003121class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
3122 """
3123 Tests for SSL renegotiation APIs.
3124 """
3125 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003126 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003127 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003128 arguments.
3129 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003130 connection = Connection(Context(TLSv1_METHOD), None)
3131 self.assertRaises(TypeError, connection.renegotiate, None)
3132
3133
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003134 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003135 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003136 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003137 any arguments.
3138 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003139 connection = Connection(Context(TLSv1_METHOD), None)
3140 self.assertRaises(TypeError, connection.total_renegotiations, None)
3141
3142
3143 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003144 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003145 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003146 renegotiations have happened.
3147 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003148 connection = Connection(Context(TLSv1_METHOD), None)
3149 self.assertEquals(connection.total_renegotiations(), 0)
3150
3151
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003152# def test_renegotiate(self):
3153# """
3154# """
3155# server, client = self._loopback()
3156
3157# server.send("hello world")
3158# self.assertEquals(client.recv(len("hello world")), "hello world")
3159
3160# self.assertEquals(server.total_renegotiations(), 0)
3161# self.assertTrue(server.renegotiate())
3162
3163# server.setblocking(False)
3164# client.setblocking(False)
3165# while server.renegotiate_pending():
3166# client.do_handshake()
3167# server.do_handshake()
3168
3169# self.assertEquals(server.total_renegotiations(), 1)
3170
3171
3172
3173
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003174class ErrorTests(TestCase):
3175 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003176 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003177 """
3178 def test_type(self):
3179 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003180 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003181 """
3182 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05003183 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05003184
3185
3186
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003187class ConstantsTests(TestCase):
3188 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003189 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003190
3191 These are values defined by OpenSSL intended only to be used as flags to
3192 OpenSSL APIs. The only assertions it seems can be made about them is
3193 their values.
3194 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003195 # unittest.TestCase has no skip mechanism
3196 if OP_NO_QUERY_MTU is not None:
3197 def test_op_no_query_mtu(self):
3198 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003199 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003200 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003201 """
3202 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
3203 else:
3204 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003205
3206
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003207 if OP_COOKIE_EXCHANGE is not None:
3208 def test_op_cookie_exchange(self):
3209 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003210 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003211 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003212 """
3213 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
3214 else:
3215 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003216
3217
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003218 if OP_NO_TICKET is not None:
3219 def test_op_no_ticket(self):
3220 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003221 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003222 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003223 """
3224 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04003225 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003226 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05003227
3228
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003229 if OP_NO_COMPRESSION is not None:
3230 def test_op_no_compression(self):
3231 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003232 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
3233 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003234 """
3235 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
3236 else:
3237 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3238
3239
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003240 def test_sess_cache_off(self):
3241 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003242 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3243 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003244 """
3245 self.assertEqual(0x0, SESS_CACHE_OFF)
3246
3247
3248 def test_sess_cache_client(self):
3249 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003250 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3251 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003252 """
3253 self.assertEqual(0x1, SESS_CACHE_CLIENT)
3254
3255
3256 def test_sess_cache_server(self):
3257 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003258 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3259 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003260 """
3261 self.assertEqual(0x2, SESS_CACHE_SERVER)
3262
3263
3264 def test_sess_cache_both(self):
3265 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003266 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3267 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003268 """
3269 self.assertEqual(0x3, SESS_CACHE_BOTH)
3270
3271
3272 def test_sess_cache_no_auto_clear(self):
3273 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003274 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3275 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3276 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003277 """
3278 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
3279
3280
3281 def test_sess_cache_no_internal_lookup(self):
3282 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003283 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3284 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3285 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003286 """
3287 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
3288
3289
3290 def test_sess_cache_no_internal_store(self):
3291 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003292 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3293 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3294 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003295 """
3296 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
3297
3298
3299 def test_sess_cache_no_internal(self):
3300 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003301 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3302 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
3303 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003304 """
3305 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
3306
3307
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04003308
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003309class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05003310 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003311 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003312 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003313 def _server(self, sock):
3314 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003315 Create a new server-side SSL :py:obj:`Connection` object wrapped around
3316 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003317 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003318 # Create the server side Connection. This is mostly setup boilerplate
3319 # - use TLSv1, use a particular certificate, etc.
3320 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003321 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
3322 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 -04003323 server_store = server_ctx.get_cert_store()
3324 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3325 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3326 server_ctx.check_privatekey()
3327 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003328 # Here the Connection is actually created. If None is passed as the 2nd
3329 # parameter, it indicates a memory BIO should be created.
3330 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003331 server_conn.set_accept_state()
3332 return server_conn
3333
3334
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003335 def _client(self, sock):
3336 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003337 Create a new client-side SSL :py:obj:`Connection` object wrapped around
3338 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003339 """
3340 # Now create the client side Connection. Similar boilerplate to the
3341 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003342 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003343 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
3344 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 -04003345 client_store = client_ctx.get_cert_store()
3346 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
3347 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
3348 client_ctx.check_privatekey()
3349 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003350 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003351 client_conn.set_connect_state()
3352 return client_conn
3353
3354
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003355 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003356 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003357 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003358 reading from the output of each and writing those bytes to the input of
3359 the other and in this way establish a connection and exchange
3360 application-level bytes with each other.
3361 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003362 server_conn = self._server(None)
3363 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003364
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003365 # There should be no key or nonces yet.
3366 self.assertIdentical(server_conn.master_key(), None)
3367 self.assertIdentical(server_conn.client_random(), None)
3368 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003369
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003370 # First, the handshake needs to happen. We'll deliver bytes back and
3371 # forth between the client and server until neither of them feels like
3372 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003373 self.assertIdentical(
3374 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003375
3376 # Now that the handshake is done, there should be a key and nonces.
3377 self.assertNotIdentical(server_conn.master_key(), None)
3378 self.assertNotIdentical(server_conn.client_random(), None)
3379 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04003380 self.assertEquals(server_conn.client_random(), client_conn.client_random())
3381 self.assertEquals(server_conn.server_random(), client_conn.server_random())
3382 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
3383 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003384
3385 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003386 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05003387
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003388 server_conn.write(important_message)
3389 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003390 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003391 (client_conn, important_message))
3392
3393 client_conn.write(important_message[::-1])
3394 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003395 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003396 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003397
3398
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003399 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003400 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003401 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003402
3403 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09003404 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003405 this test fails, there must be a problem outside the memory BIO
3406 code, as no memory BIO is involved here). Even though this isn't a
3407 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003408 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04003409 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003410
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003411 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05003412 client_conn.send(important_message)
3413 msg = server_conn.recv(1024)
3414 self.assertEqual(msg, important_message)
3415
3416 # Again in the other direction, just for fun.
3417 important_message = important_message[::-1]
3418 server_conn.send(important_message)
3419 msg = client_conn.recv(1024)
3420 self.assertEqual(msg, important_message)
3421
3422
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04003423 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003424 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003425 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
3426 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003427 """
3428 context = Context(SSLv3_METHOD)
3429 client = socket()
3430 clientSSL = Connection(context, client)
Alex Gaynor43307782015-09-04 09:05:45 -04003431 self.assertRaises(TypeError, clientSSL.bio_read, 100)
3432 self.assertRaises(TypeError, clientSSL.bio_write, "foo")
Alex Gaynor7e8b61e2015-09-04 13:13:05 -04003433 self.assertRaises(TypeError, clientSSL.bio_shutdown)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003434
3435
3436 def test_outgoingOverflow(self):
3437 """
3438 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09003439 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003440 returned and that many bytes from the beginning of the input can be
3441 read from the other end of the connection.
3442 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003443 server = self._server(None)
3444 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003445
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003446 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003447
3448 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003449 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003450 # Sanity check. We're trying to test what happens when the entire
3451 # input can't be sent. If the entire input was sent, this test is
3452 # meaningless.
3453 self.assertTrue(sent < size)
3454
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003455 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003456 self.assertIdentical(receiver, server)
3457
3458 # We can rely on all of these bytes being received at once because
3459 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
3460 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003461
3462
3463 def test_shutdown(self):
3464 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003465 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
3466 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003467 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003468 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003469 server.bio_shutdown()
3470 e = self.assertRaises(Error, server.recv, 1024)
3471 # We don't want WantReadError or ZeroReturnError or anything - it's a
3472 # handshake failure.
3473 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003474
3475
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003476 def test_unexpectedEndOfFile(self):
3477 """
3478 If the connection is lost before an orderly SSL shutdown occurs,
3479 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
3480 "Unexpected EOF".
3481 """
3482 server_conn, client_conn = self._loopback()
3483 client_conn.sock_shutdown(SHUT_RDWR)
3484 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
3485 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
3486
3487
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003488 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003489 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003490 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 -04003491
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003492 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003493 before the client and server are connected to each other. This
3494 function should specify a list of CAs for the server to send to the
3495 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09003496 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003497 times.
3498 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003499 server = self._server(None)
3500 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003501 self.assertEqual(client.get_client_ca_list(), [])
3502 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003503 ctx = server.get_context()
3504 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003505 self.assertEqual(client.get_client_ca_list(), [])
3506 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003507 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003508 self.assertEqual(client.get_client_ca_list(), expected)
3509 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003510
3511
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003512 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003513 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003514 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003515 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003516 """
3517 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003518 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
3519 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
3520 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003521
3522
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003523 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003524 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003525 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003526 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09003527 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003528 after the connection is set up.
3529 """
3530 def no_ca(ctx):
3531 ctx.set_client_ca_list([])
3532 return []
3533 self._check_client_ca_list(no_ca)
3534
3535
3536 def test_set_one_ca_list(self):
3537 """
3538 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003539 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003540 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003541 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003542 X509Name after the connection is set up.
3543 """
3544 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3545 cadesc = cacert.get_subject()
3546 def single_ca(ctx):
3547 ctx.set_client_ca_list([cadesc])
3548 return [cadesc]
3549 self._check_client_ca_list(single_ca)
3550
3551
3552 def test_set_multiple_ca_list(self):
3553 """
3554 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003555 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003556 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003557 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003558 X509Names after the connection is set up.
3559 """
3560 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3561 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3562
3563 sedesc = secert.get_subject()
3564 cldesc = clcert.get_subject()
3565
3566 def multiple_ca(ctx):
3567 L = [sedesc, cldesc]
3568 ctx.set_client_ca_list(L)
3569 return L
3570 self._check_client_ca_list(multiple_ca)
3571
3572
3573 def test_reset_ca_list(self):
3574 """
3575 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09003576 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003577 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003578 """
3579 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3580 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3581 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3582
3583 cadesc = cacert.get_subject()
3584 sedesc = secert.get_subject()
3585 cldesc = clcert.get_subject()
3586
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003587 def changed_ca(ctx):
3588 ctx.set_client_ca_list([sedesc, cldesc])
3589 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003590 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003591 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003592
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003593
3594 def test_mutated_ca_list(self):
3595 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003596 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003597 afterwards, this does not affect the list of CA names sent to the
3598 client.
3599 """
3600 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3601 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3602
3603 cadesc = cacert.get_subject()
3604 sedesc = secert.get_subject()
3605
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003606 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003607 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003608 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003609 L.append(sedesc)
3610 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003611 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003612
3613
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003614 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003615 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003616 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003617 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003618 """
3619 ctx = Context(TLSv1_METHOD)
3620 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003621 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003622 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003623 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003624
3625
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003626 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003627 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003628 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09003629 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003630 """
3631 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3632 cadesc = cacert.get_subject()
3633 def single_ca(ctx):
3634 ctx.add_client_ca(cacert)
3635 return [cadesc]
3636 self._check_client_ca_list(single_ca)
3637
3638
3639 def test_multiple_add_client_ca(self):
3640 """
3641 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09003642 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003643 """
3644 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3645 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3646
3647 cadesc = cacert.get_subject()
3648 sedesc = secert.get_subject()
3649
3650 def multiple_ca(ctx):
3651 ctx.add_client_ca(cacert)
3652 ctx.add_client_ca(secert)
3653 return [cadesc, sedesc]
3654 self._check_client_ca_list(multiple_ca)
3655
3656
3657 def test_set_and_add_client_ca(self):
3658 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003659 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
3660 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003661 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003662 """
3663 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3664 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3665 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3666
3667 cadesc = cacert.get_subject()
3668 sedesc = secert.get_subject()
3669 cldesc = clcert.get_subject()
3670
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003671 def mixed_set_add_ca(ctx):
3672 ctx.set_client_ca_list([cadesc, sedesc])
3673 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003674 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003675 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003676
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003677
3678 def test_set_after_add_client_ca(self):
3679 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003680 A call to :py:obj:`Context.set_client_ca_list` after a call to
3681 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003682 call with the names specified by the latter cal.
3683 """
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()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003690
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003691 def set_replaces_add_ca(ctx):
3692 ctx.add_client_ca(clcert)
3693 ctx.set_client_ca_list([cadesc])
3694 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003695 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003696 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003697
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003698
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003699
3700class ConnectionBIOTests(TestCase):
3701 """
3702 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3703 """
3704 def test_wantReadError(self):
3705 """
3706 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
3707 if there are no bytes available to be read from the BIO.
3708 """
3709 ctx = Context(TLSv1_METHOD)
3710 conn = Connection(ctx, None)
3711 self.assertRaises(WantReadError, conn.bio_read, 1024)
3712
3713
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003714 def test_buffer_size(self):
3715 """
3716 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3717 number of bytes to read and return.
3718 """
3719 ctx = Context(TLSv1_METHOD)
3720 conn = Connection(ctx, None)
3721 conn.set_connect_state()
3722 try:
3723 conn.do_handshake()
3724 except WantReadError:
3725 pass
3726 data = conn.bio_read(2)
3727 self.assertEqual(2, len(data))
3728
3729
3730 if not PY3:
3731 def test_buffer_size_long(self):
3732 """
3733 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3734 :py:obj:`long` as well as :py:obj:`int`.
3735 """
3736 ctx = Context(TLSv1_METHOD)
3737 conn = Connection(ctx, None)
3738 conn.set_connect_state()
3739 try:
3740 conn.do_handshake()
3741 except WantReadError:
3742 pass
3743 data = conn.bio_read(long(2))
3744 self.assertEqual(2, len(data))
3745
3746
3747
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003748
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003749class InfoConstantTests(TestCase):
3750 """
3751 Tests for assorted constants exposed for use in info callbacks.
3752 """
3753 def test_integers(self):
3754 """
3755 All of the info constants are integers.
3756
3757 This is a very weak test. It would be nice to have one that actually
3758 verifies that as certain info events happen, the value passed to the
3759 info callback matches up with the constant exposed by OpenSSL.SSL.
3760 """
3761 for const in [
3762 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3763 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3764 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3765 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3766 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
3767 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
3768
3769 self.assertTrue(isinstance(const, int))
3770
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003771
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003772if __name__ == '__main__':
3773 main()