blob: cb92020e351cc0ea4abe19b2dcba7dbdf6bae623 [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 Schlawackb4f02402015-09-05 20:48:34 +0200102skip_if_py3 = pytest.mark.skipif(PY3, reason="Python 2 only")
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200103
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(
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001324 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None
1325 ) # pragma: nocover
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001326 self.assertEquals(
1327 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001328
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001329 def test_load_tmp_dh_wrong_args(self):
1330 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001331 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with
1332 the wrong number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001333 """
1334 context = Context(TLSv1_METHOD)
1335 self.assertRaises(TypeError, context.load_tmp_dh)
1336 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1337 self.assertRaises(TypeError, context.load_tmp_dh, object())
1338
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001339 def test_load_tmp_dh_missing_file(self):
1340 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001341 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the
1342 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001343 """
1344 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001345 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001346
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001347 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001348 """
1349 Verify that calling ``Context.load_tmp_dh`` with the given filename
1350 does not raise an exception.
1351 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001352 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001353 with open(dhfilename, "w") as dhfile:
1354 dhfile.write(dhparam)
1355
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001356 context.load_tmp_dh(dhfilename)
1357 # XXX What should I assert here? -exarkun
1358
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001359 def test_load_tmp_dh_bytes(self):
1360 """
1361 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1362 specified file (given as ``bytes``).
1363 """
1364 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001365 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001366 )
1367
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001368 def test_load_tmp_dh_unicode(self):
1369 """
1370 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1371 specified file (given as ``unicode``).
1372 """
1373 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001374 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001375 )
1376
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001377 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001378 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001379 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001380 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001381 """
1382 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001383 for curve in get_elliptic_curves():
1384 # The only easily "assertable" thing is that it does not raise an
1385 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001386 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001387
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001388 def test_set_cipher_list_bytes(self):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001389 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001390 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
1391 ciphers which connections created with the context object will be able
1392 to choose from.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001393 """
1394 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001395 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001396 conn = Connection(context, None)
1397 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001398
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001399 def test_set_cipher_list_text(self):
1400 """
1401 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
1402 the ciphers which connections created with the context object will be
1403 able to choose from.
1404 """
1405 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -05001406 context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001407 conn = Connection(context, None)
1408 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
1409
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001410 def test_set_cipher_list_wrong_args(self):
1411 """
Jean-Paul Calderone17044832014-01-18 10:20:11 -05001412 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
1413 passed zero arguments or more than one argument or when passed a
1414 non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001415 passed an incorrect cipher list string.
1416 """
1417 context = Context(TLSv1_METHOD)
1418 self.assertRaises(TypeError, context.set_cipher_list)
1419 self.assertRaises(TypeError, context.set_cipher_list, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001420 self.assertRaises(
1421 TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object()
1422 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001423
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001424 self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001425
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001426 def test_set_session_cache_mode_wrong_args(self):
1427 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001428 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1429 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001430 """
1431 context = Context(TLSv1_METHOD)
1432 self.assertRaises(TypeError, context.set_session_cache_mode)
1433 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1434
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001435 def test_get_session_cache_mode_wrong_args(self):
1436 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001437 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1438 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001439 """
1440 context = Context(TLSv1_METHOD)
1441 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1442
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001443 def test_session_cache_mode(self):
1444 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001445 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1446 cached. The setting can be retrieved via
1447 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001448 """
1449 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001450 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001451 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1452 self.assertEqual(SESS_CACHE_OFF, off)
1453 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1454
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001455 @skip_if_py3
1456 def test_session_cache_mode_long(self):
1457 """
1458 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1459 of type :py:obj:`long` as well as :py:obj:`int`.
1460 """
1461 context = Context(TLSv1_METHOD)
1462 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1463 self.assertEqual(
1464 SESS_CACHE_BOTH, context.get_session_cache_mode())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001465
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001466 def test_get_cert_store(self):
1467 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001468 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store`
1469 instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001470 """
1471 context = Context(TLSv1_METHOD)
1472 store = context.get_cert_store()
1473 self.assertIsInstance(store, X509Store)
1474
1475
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001476class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1477 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001478 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its
1479 interaction with :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001480 """
1481 def test_wrong_args(self):
1482 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001483 :py:obj:`Context.set_tlsext_servername_callback` raises
1484 :py:obj:`TypeError` if called with other than one argument.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001485 """
1486 context = Context(TLSv1_METHOD)
1487 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1488 self.assertRaises(
1489 TypeError, context.set_tlsext_servername_callback, 1, 2)
1490
1491 def test_old_callback_forgotten(self):
1492 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001493 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify
1494 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001495 """
1496 def callback(connection):
1497 pass
1498
1499 def replacement(connection):
1500 pass
1501
1502 context = Context(TLSv1_METHOD)
1503 context.set_tlsext_servername_callback(callback)
1504
1505 tracker = ref(callback)
1506 del callback
1507
1508 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001509
1510 # One run of the garbage collector happens to work on CPython. PyPy
1511 # doesn't collect the underlying object until a second run for whatever
1512 # reason. That's fine, it still demonstrates our code has properly
1513 # dropped the reference.
1514 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001515 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001516
1517 callback = tracker()
1518 if callback is not None:
1519 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001520 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001521 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001522
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001523 def test_no_servername(self):
1524 """
1525 When a client specifies no server name, the callback passed to
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001526 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the
1527 result of :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001528 """
1529 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001530
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001531 def servername(conn):
1532 args.append((conn, conn.get_servername()))
1533 context = Context(TLSv1_METHOD)
1534 context.set_tlsext_servername_callback(servername)
1535
1536 # Lose our reference to it. The Context is responsible for keeping it
1537 # alive now.
1538 del servername
1539 collect()
1540
1541 # Necessary to actually accept the connection
1542 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001543 context.use_certificate(
1544 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001545
1546 # Do a little connection to trigger the logic
1547 server = Connection(context, None)
1548 server.set_accept_state()
1549
1550 client = Connection(Context(TLSv1_METHOD), None)
1551 client.set_connect_state()
1552
1553 self._interactInMemory(server, client)
1554
1555 self.assertEqual([(server, None)], args)
1556
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001557 def test_servername(self):
1558 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001559 When a client specifies a server name in its hello message, the
1560 callback passed to :py:obj:`Contexts.set_tlsext_servername_callback` is
1561 invoked and the result of :py:obj:`Connection.get_servername` is that
1562 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001563 """
1564 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001565
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001566 def servername(conn):
1567 args.append((conn, conn.get_servername()))
1568 context = Context(TLSv1_METHOD)
1569 context.set_tlsext_servername_callback(servername)
1570
1571 # Necessary to actually accept the connection
1572 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001573 context.use_certificate(
1574 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001575
1576 # Do a little connection to trigger the logic
1577 server = Connection(context, None)
1578 server.set_accept_state()
1579
1580 client = Connection(Context(TLSv1_METHOD), None)
1581 client.set_connect_state()
1582 client.set_tlsext_host_name(b("foo1.example.com"))
1583
1584 self._interactInMemory(server, client)
1585
1586 self.assertEqual([(server, b("foo1.example.com"))], args)
1587
1588
Cory Benfield84a121e2014-03-31 20:30:25 +01001589class NextProtoNegotiationTests(TestCase, _LoopbackMixin):
1590 """
1591 Test for Next Protocol Negotiation in PyOpenSSL.
1592 """
Cory Benfieldba1820d2015-04-13 17:39:12 -04001593 if _lib.Cryptography_HAS_NEXTPROTONEG:
1594 def test_npn_success(self):
1595 """
1596 Tests that clients and servers that agree on the negotiated next
1597 protocol can correct establish a connection, and that the agreed
1598 protocol is reported by the connections.
1599 """
1600 advertise_args = []
1601 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001602
Cory Benfieldba1820d2015-04-13 17:39:12 -04001603 def advertise(conn):
1604 advertise_args.append((conn,))
1605 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001606
Cory Benfieldba1820d2015-04-13 17:39:12 -04001607 def select(conn, options):
1608 select_args.append((conn, options))
1609 return b'spdy/2'
Cory Benfield84a121e2014-03-31 20:30:25 +01001610
Cory Benfieldba1820d2015-04-13 17:39:12 -04001611 server_context = Context(TLSv1_METHOD)
1612 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001613
Cory Benfieldba1820d2015-04-13 17:39:12 -04001614 client_context = Context(TLSv1_METHOD)
1615 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001616
Cory Benfieldba1820d2015-04-13 17:39:12 -04001617 # Necessary to actually accept the connection
1618 server_context.use_privatekey(
1619 load_privatekey(FILETYPE_PEM, server_key_pem))
1620 server_context.use_certificate(
1621 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001622
Cory Benfieldba1820d2015-04-13 17:39:12 -04001623 # Do a little connection to trigger the logic
1624 server = Connection(server_context, None)
1625 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001626
Cory Benfieldba1820d2015-04-13 17:39:12 -04001627 client = Connection(client_context, None)
1628 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001629
Cory Benfieldba1820d2015-04-13 17:39:12 -04001630 self._interactInMemory(server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001631
Cory Benfieldba1820d2015-04-13 17:39:12 -04001632 self.assertEqual([(server,)], advertise_args)
1633 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001634
Cory Benfieldba1820d2015-04-13 17:39:12 -04001635 self.assertEqual(server.get_next_proto_negotiated(), b'spdy/2')
1636 self.assertEqual(client.get_next_proto_negotiated(), b'spdy/2')
Cory Benfield84a121e2014-03-31 20:30:25 +01001637
Cory Benfieldba1820d2015-04-13 17:39:12 -04001638 def test_npn_client_fail(self):
1639 """
1640 Tests that when clients and servers cannot agree on what protocol
1641 to use next that the TLS connection does not get established.
1642 """
1643 advertise_args = []
1644 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001645
Cory Benfieldba1820d2015-04-13 17:39:12 -04001646 def advertise(conn):
1647 advertise_args.append((conn,))
1648 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001649
Cory Benfieldba1820d2015-04-13 17:39:12 -04001650 def select(conn, options):
1651 select_args.append((conn, options))
1652 return b''
Cory Benfield84a121e2014-03-31 20:30:25 +01001653
Cory Benfieldba1820d2015-04-13 17:39:12 -04001654 server_context = Context(TLSv1_METHOD)
1655 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001656
Cory Benfieldba1820d2015-04-13 17:39:12 -04001657 client_context = Context(TLSv1_METHOD)
1658 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001659
Cory Benfieldba1820d2015-04-13 17:39:12 -04001660 # Necessary to actually accept the connection
1661 server_context.use_privatekey(
1662 load_privatekey(FILETYPE_PEM, server_key_pem))
1663 server_context.use_certificate(
1664 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001665
Cory Benfieldba1820d2015-04-13 17:39:12 -04001666 # Do a little connection to trigger the logic
1667 server = Connection(server_context, None)
1668 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001669
Cory Benfieldba1820d2015-04-13 17:39:12 -04001670 client = Connection(client_context, None)
1671 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001672
Cory Benfieldba1820d2015-04-13 17:39:12 -04001673 # If the client doesn't return anything, the connection will fail.
1674 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001675
Cory Benfieldba1820d2015-04-13 17:39:12 -04001676 self.assertEqual([(server,)], advertise_args)
1677 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001678
Cory Benfieldba1820d2015-04-13 17:39:12 -04001679 def test_npn_select_error(self):
1680 """
1681 Test that we can handle exceptions in the select callback. If
1682 select fails it should be fatal to the connection.
1683 """
1684 advertise_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001685
Cory Benfieldba1820d2015-04-13 17:39:12 -04001686 def advertise(conn):
1687 advertise_args.append((conn,))
1688 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001689
Cory Benfieldba1820d2015-04-13 17:39:12 -04001690 def select(conn, options):
1691 raise TypeError
Cory Benfield0ea76e72015-03-22 09:05:28 +00001692
Cory Benfieldba1820d2015-04-13 17:39:12 -04001693 server_context = Context(TLSv1_METHOD)
1694 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001695
Cory Benfieldba1820d2015-04-13 17:39:12 -04001696 client_context = Context(TLSv1_METHOD)
1697 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001698
Cory Benfieldba1820d2015-04-13 17:39:12 -04001699 # Necessary to actually accept the connection
1700 server_context.use_privatekey(
1701 load_privatekey(FILETYPE_PEM, server_key_pem))
1702 server_context.use_certificate(
1703 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001704
Cory Benfieldba1820d2015-04-13 17:39:12 -04001705 # Do a little connection to trigger the logic
1706 server = Connection(server_context, None)
1707 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001708
Cory Benfieldba1820d2015-04-13 17:39:12 -04001709 client = Connection(client_context, None)
1710 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001711
Cory Benfieldba1820d2015-04-13 17:39:12 -04001712 # If the callback throws an exception it should be raised here.
1713 self.assertRaises(
1714 TypeError, self._interactInMemory, server, client
1715 )
1716 self.assertEqual([(server,)], advertise_args)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001717
Cory Benfieldba1820d2015-04-13 17:39:12 -04001718 def test_npn_advertise_error(self):
1719 """
1720 Test that we can handle exceptions in the advertise callback. If
1721 advertise fails no NPN is advertised to the client.
1722 """
1723 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001724
Cory Benfieldba1820d2015-04-13 17:39:12 -04001725 def advertise(conn):
1726 raise TypeError
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001727
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001728 def select(conn, options): # pragma: nocover
1729 """
1730 Assert later that no args are actually appended.
1731 """
Cory Benfieldba1820d2015-04-13 17:39:12 -04001732 select_args.append((conn, options))
1733 return b''
Cory Benfield0ea76e72015-03-22 09:05:28 +00001734
Cory Benfieldba1820d2015-04-13 17:39:12 -04001735 server_context = Context(TLSv1_METHOD)
1736 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001737
Cory Benfieldba1820d2015-04-13 17:39:12 -04001738 client_context = Context(TLSv1_METHOD)
1739 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001740
Cory Benfieldba1820d2015-04-13 17:39:12 -04001741 # Necessary to actually accept the connection
1742 server_context.use_privatekey(
1743 load_privatekey(FILETYPE_PEM, server_key_pem))
1744 server_context.use_certificate(
1745 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001746
Cory Benfieldba1820d2015-04-13 17:39:12 -04001747 # Do a little connection to trigger the logic
1748 server = Connection(server_context, None)
1749 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001750
Cory Benfieldba1820d2015-04-13 17:39:12 -04001751 client = Connection(client_context, None)
1752 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001753
Cory Benfieldba1820d2015-04-13 17:39:12 -04001754 # If the client doesn't return anything, the connection will fail.
1755 self.assertRaises(
1756 TypeError, self._interactInMemory, server, client
1757 )
1758 self.assertEqual([], select_args)
1759
1760 else:
1761 # No NPN.
1762 def test_npn_not_implemented(self):
1763 # Test the context methods first.
1764 context = Context(TLSv1_METHOD)
1765 fail_methods = [
1766 context.set_npn_advertise_callback,
1767 context.set_npn_select_callback,
1768 ]
1769 for method in fail_methods:
1770 self.assertRaises(
1771 NotImplementedError, method, None
1772 )
1773
1774 # Now test a connection.
1775 conn = Connection(context)
1776 fail_methods = [
1777 conn.get_next_proto_negotiated,
1778 ]
1779 for method in fail_methods:
1780 self.assertRaises(NotImplementedError, method)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001781
1782
Cory Benfield12eae892014-06-07 15:42:56 +01001783class ApplicationLayerProtoNegotiationTests(TestCase, _LoopbackMixin):
1784 """
1785 Tests for ALPN in PyOpenSSL.
1786 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001787 # Skip tests on versions that don't support ALPN.
1788 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001789
Cory Benfielde46fa842015-04-13 16:50:49 -04001790 def test_alpn_success(self):
1791 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001792 Clients and servers that agree on the negotiated ALPN protocol can
1793 correct establish a connection, and the agreed protocol is reported
1794 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001795 """
1796 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001797
Cory Benfielde46fa842015-04-13 16:50:49 -04001798 def select(conn, options):
1799 select_args.append((conn, options))
1800 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001801
Cory Benfielde46fa842015-04-13 16:50:49 -04001802 client_context = Context(TLSv1_METHOD)
1803 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001804
Cory Benfielde46fa842015-04-13 16:50:49 -04001805 server_context = Context(TLSv1_METHOD)
1806 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001807
Cory Benfielde46fa842015-04-13 16:50:49 -04001808 # Necessary to actually accept the connection
1809 server_context.use_privatekey(
1810 load_privatekey(FILETYPE_PEM, server_key_pem))
1811 server_context.use_certificate(
1812 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001813
Cory Benfielde46fa842015-04-13 16:50:49 -04001814 # Do a little connection to trigger the logic
1815 server = Connection(server_context, None)
1816 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001817
Cory Benfielde46fa842015-04-13 16:50:49 -04001818 client = Connection(client_context, None)
1819 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001820
Cory Benfielde46fa842015-04-13 16:50:49 -04001821 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001822
Cory Benfielde46fa842015-04-13 16:50:49 -04001823 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
1824
1825 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1826 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001827
Cory Benfielde46fa842015-04-13 16:50:49 -04001828 def test_alpn_set_on_connection(self):
1829 """
1830 The same as test_alpn_success, but setting the ALPN protocols on
1831 the connection rather than the context.
1832 """
1833 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001834
Cory Benfielde46fa842015-04-13 16:50:49 -04001835 def select(conn, options):
1836 select_args.append((conn, options))
1837 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001838
Cory Benfielde46fa842015-04-13 16:50:49 -04001839 # Setup the client context but don't set any ALPN protocols.
1840 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001841
Cory Benfielde46fa842015-04-13 16:50:49 -04001842 server_context = Context(TLSv1_METHOD)
1843 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001844
Cory Benfielde46fa842015-04-13 16:50:49 -04001845 # Necessary to actually accept the connection
1846 server_context.use_privatekey(
1847 load_privatekey(FILETYPE_PEM, server_key_pem))
1848 server_context.use_certificate(
1849 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001850
Cory Benfielde46fa842015-04-13 16:50:49 -04001851 # Do a little connection to trigger the logic
1852 server = Connection(server_context, None)
1853 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001854
Cory Benfielde46fa842015-04-13 16:50:49 -04001855 # Set the ALPN protocols on the client connection.
1856 client = Connection(client_context, None)
1857 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1858 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001859
Cory Benfielde46fa842015-04-13 16:50:49 -04001860 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001861
Cory Benfielde46fa842015-04-13 16:50:49 -04001862 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001863
Cory Benfielde46fa842015-04-13 16:50:49 -04001864 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1865 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001866
Cory Benfielde46fa842015-04-13 16:50:49 -04001867 def test_alpn_server_fail(self):
1868 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001869 When clients and servers cannot agree on what protocol to use next
1870 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001871 """
1872 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001873
Cory Benfielde46fa842015-04-13 16:50:49 -04001874 def select(conn, options):
1875 select_args.append((conn, options))
1876 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001877
Cory Benfielde46fa842015-04-13 16:50:49 -04001878 client_context = Context(TLSv1_METHOD)
1879 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001880
Cory Benfielde46fa842015-04-13 16:50:49 -04001881 server_context = Context(TLSv1_METHOD)
1882 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001883
Cory Benfielde46fa842015-04-13 16:50:49 -04001884 # Necessary to actually accept the connection
1885 server_context.use_privatekey(
1886 load_privatekey(FILETYPE_PEM, server_key_pem))
1887 server_context.use_certificate(
1888 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001889
Cory Benfielde46fa842015-04-13 16:50:49 -04001890 # Do a little connection to trigger the logic
1891 server = Connection(server_context, None)
1892 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001893
Cory Benfielde46fa842015-04-13 16:50:49 -04001894 client = Connection(client_context, None)
1895 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001896
Cory Benfielde46fa842015-04-13 16:50:49 -04001897 # If the client doesn't return anything, the connection will fail.
1898 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001899
Cory Benfielde46fa842015-04-13 16:50:49 -04001900 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001901
Cory Benfielde46fa842015-04-13 16:50:49 -04001902 def test_alpn_no_server(self):
1903 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001904 When clients and servers cannot agree on what protocol to use next
1905 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04001906 """
1907 client_context = Context(TLSv1_METHOD)
1908 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04001909
Cory Benfielde46fa842015-04-13 16:50:49 -04001910 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04001911
Cory Benfielde46fa842015-04-13 16:50:49 -04001912 # Necessary to actually accept the connection
1913 server_context.use_privatekey(
1914 load_privatekey(FILETYPE_PEM, server_key_pem))
1915 server_context.use_certificate(
1916 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04001917
Cory Benfielde46fa842015-04-13 16:50:49 -04001918 # Do a little connection to trigger the logic
1919 server = Connection(server_context, None)
1920 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001921
Cory Benfielde46fa842015-04-13 16:50:49 -04001922 client = Connection(client_context, None)
1923 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001924
Cory Benfielde46fa842015-04-13 16:50:49 -04001925 # Do the dance.
1926 self._interactInMemory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04001927
Cory Benfielde46fa842015-04-13 16:50:49 -04001928 self.assertEqual(client.get_alpn_proto_negotiated(), b'')
Cory Benfielde3d57152015-04-11 17:57:35 -04001929
Cory Benfielde46fa842015-04-13 16:50:49 -04001930 def test_alpn_callback_exception(self):
1931 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001932 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04001933 """
1934 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001935
Cory Benfielde46fa842015-04-13 16:50:49 -04001936 def select(conn, options):
1937 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04001938 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001939
Cory Benfielde46fa842015-04-13 16:50:49 -04001940 client_context = Context(TLSv1_METHOD)
1941 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04001942
Cory Benfielde46fa842015-04-13 16:50:49 -04001943 server_context = Context(TLSv1_METHOD)
1944 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04001945
Cory Benfielde46fa842015-04-13 16:50:49 -04001946 # Necessary to actually accept the connection
1947 server_context.use_privatekey(
1948 load_privatekey(FILETYPE_PEM, server_key_pem))
1949 server_context.use_certificate(
1950 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04001951
Cory Benfielde46fa842015-04-13 16:50:49 -04001952 # Do a little connection to trigger the logic
1953 server = Connection(server_context, None)
1954 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001955
Cory Benfielde46fa842015-04-13 16:50:49 -04001956 client = Connection(client_context, None)
1957 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001958
Cory Benfielde46fa842015-04-13 16:50:49 -04001959 self.assertRaises(
1960 TypeError, self._interactInMemory, server, client
1961 )
1962 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfieldf1177e72015-04-12 09:11:49 -04001963
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001964 else:
1965 # No ALPN.
1966 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04001967 """
1968 If ALPN is not in OpenSSL, we should raise NotImplementedError.
1969 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001970 # Test the context methods first.
1971 context = Context(TLSv1_METHOD)
Cory Benfield307e9e62015-04-13 18:21:12 -04001972 self.assertRaises(
1973 NotImplementedError, context.set_alpn_protos, None
1974 )
1975 self.assertRaises(
1976 NotImplementedError, context.set_alpn_select_callback, None
1977 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001978
1979 # Now test a connection.
1980 conn = Connection(context)
Cory Benfield307e9e62015-04-13 18:21:12 -04001981 self.assertRaises(
Alex Gaynor68417232015-09-04 07:56:29 -04001982 NotImplementedError, conn.set_alpn_protos, None
Cory Benfield307e9e62015-04-13 18:21:12 -04001983 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001984
Cory Benfieldf1177e72015-04-12 09:11:49 -04001985
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001986class SessionTests(TestCase):
1987 """
1988 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1989 """
1990 def test_construction(self):
1991 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001992 :py:class:`Session` can be constructed with no arguments, creating
1993 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001994 """
1995 new_session = Session()
1996 self.assertTrue(isinstance(new_session, Session))
1997
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001998 def test_construction_wrong_args(self):
1999 """
2000 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
2001 is raised.
2002 """
2003 self.assertRaises(TypeError, Session, 123)
2004 self.assertRaises(TypeError, Session, "hello")
2005 self.assertRaises(TypeError, Session, object())
2006
2007
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002008class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05002009 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002010 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002011 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002012 # XXX get_peer_certificate -> None
2013 # XXX sock_shutdown
2014 # XXX master_key -> TypeError
2015 # XXX server_random -> TypeError
2016 # XXX state_string
2017 # XXX connect -> TypeError
2018 # XXX connect_ex -> TypeError
2019 # XXX set_connect_state -> TypeError
2020 # XXX set_accept_state -> TypeError
2021 # XXX renegotiate_pending
2022 # XXX do_handshake -> TypeError
2023 # XXX bio_read -> TypeError
2024 # XXX recv -> TypeError
2025 # XXX send -> TypeError
2026 # XXX bio_write -> TypeError
2027
Rick Deane15b1472009-07-09 15:53:42 -05002028 def test_type(self):
2029 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002030 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same
2031 type object and can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002032 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002033 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05002034 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002035 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002036
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002037 def test_get_context(self):
2038 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002039 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance
2040 used to construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002041 """
2042 context = Context(TLSv1_METHOD)
2043 connection = Connection(context, None)
2044 self.assertIdentical(connection.get_context(), context)
2045
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002046 def test_get_context_wrong_args(self):
2047 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002048 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called
2049 with any arguments.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002050 """
2051 connection = Connection(Context(TLSv1_METHOD), None)
2052 self.assertRaises(TypeError, connection.get_context, None)
2053
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002054 def test_set_context_wrong_args(self):
2055 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002056 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called
2057 with a non-:py:obj:`Context` instance argument or with any number of
2058 arguments other than 1.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002059 """
2060 ctx = Context(TLSv1_METHOD)
2061 connection = Connection(ctx, None)
2062 self.assertRaises(TypeError, connection.set_context)
2063 self.assertRaises(TypeError, connection.set_context, object())
2064 self.assertRaises(TypeError, connection.set_context, "hello")
2065 self.assertRaises(TypeError, connection.set_context, 1)
2066 self.assertRaises(TypeError, connection.set_context, 1, 2)
2067 self.assertRaises(
2068 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
2069 self.assertIdentical(ctx, connection.get_context())
2070
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002071 def test_set_context(self):
2072 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002073 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context`
2074 instance to be used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002075 """
2076 original = Context(SSLv23_METHOD)
2077 replacement = Context(TLSv1_METHOD)
2078 connection = Connection(original, None)
2079 connection.set_context(replacement)
2080 self.assertIdentical(replacement, connection.get_context())
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002081 # Lose our references to the contexts, just in case the Connection
2082 # isn't properly managing its own contributions to their reference
2083 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002084 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002085 collect()
2086
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002087 def test_set_tlsext_host_name_wrong_args(self):
2088 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002089 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte
2090 string argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09002091 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002092 """
2093 conn = Connection(Context(TLSv1_METHOD), None)
2094 self.assertRaises(TypeError, conn.set_tlsext_host_name)
2095 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
2096 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
2097 self.assertRaises(
2098 TypeError, conn.set_tlsext_host_name, b("with\0null"))
2099
Abraham Martinc5484ba2015-03-25 15:33:05 +00002100 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002101 # On Python 3.x, don't accidentally implicitly convert from text.
2102 self.assertRaises(
2103 TypeError,
2104 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002105
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002106 def test_get_servername_wrong_args(self):
2107 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002108 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if
2109 called with any arguments.
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002110 """
2111 connection = Connection(Context(TLSv1_METHOD), None)
2112 self.assertRaises(TypeError, connection.get_servername, object())
2113 self.assertRaises(TypeError, connection.get_servername, 1)
2114 self.assertRaises(TypeError, connection.get_servername, "hello")
2115
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002116 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002117 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002118 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002119 immediate read.
2120 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002121 connection = Connection(Context(TLSv1_METHOD), None)
2122 self.assertEquals(connection.pending(), 0)
2123
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002124 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002125 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002126 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with
2127 any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002128 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002129 connection = Connection(Context(TLSv1_METHOD), None)
2130 self.assertRaises(TypeError, connection.pending, None)
2131
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002132 def test_peek(self):
2133 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002134 :py:obj:`Connection.recv` peeks into the connection if
2135 :py:obj:`socket.MSG_PEEK` is passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002136 """
2137 server, client = self._loopback()
2138 server.send(b('xy'))
2139 self.assertEqual(client.recv(2, MSG_PEEK), b('xy'))
2140 self.assertEqual(client.recv(2, MSG_PEEK), b('xy'))
2141 self.assertEqual(client.recv(2), b('xy'))
2142
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002143 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002144 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002145 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with
2146 a non-address argument or with the wrong number of arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002147 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002148 connection = Connection(Context(TLSv1_METHOD), socket())
2149 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002150 self.assertRaises(TypeError, connection.connect)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002151 self.assertRaises(
2152 TypeError, connection.connect, ("127.0.0.1", 1), None
2153 )
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002154
kjavfe508d62015-09-02 12:20:35 +01002155 def test_connection_undefined_attr(self):
2156 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002157 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with
2158 a non-address argument or with the wrong number of arguments.
kjavfe508d62015-09-02 12:20:35 +01002159 """
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002160
kjavfe508d62015-09-02 12:20:35 +01002161 def attr_access_test(connection):
2162 return connection.an_attribute_which_is_not_defined
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002163
kjavfe508d62015-09-02 12:20:35 +01002164 connection = Connection(Context(TLSv1_METHOD), None)
2165 self.assertRaises(AttributeError, attr_access_test, connection)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002166
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002167 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002168 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002169 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the
2170 underlying socket connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002171 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002172 client = socket()
2173 context = Context(TLSv1_METHOD)
2174 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002175 # pytest.raises here doesn't work because of a bug in py.test on Python
2176 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002177 try:
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002178 clientSSL.connect(("127.0.0.1", 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002179 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002180 exc = e
2181 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002182
2183 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002184 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002185 :py:obj:`Connection.connect` establishes a connection to the specified
2186 address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002187 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002188 port = socket()
2189 port.bind(('', 0))
2190 port.listen(3)
2191
2192 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002193 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2194 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002195
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002196 @pytest.mark.skipif(
2197 platform == "darwin",
2198 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2199 )
2200 def test_connect_ex(self):
2201 """
2202 If there is a connection error, :py:obj:`Connection.connect_ex`
2203 returns the errno instead of raising an exception.
2204 """
2205 port = socket()
2206 port.bind(('', 0))
2207 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002208
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002209 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2210 clientSSL.setblocking(False)
2211 result = clientSSL.connect_ex(port.getsockname())
2212 expected = (EINPROGRESS, EWOULDBLOCK)
2213 self.assertTrue(
2214 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002215
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002216 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002217 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002218 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with
2219 any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002220 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002221 connection = Connection(Context(TLSv1_METHOD), socket())
2222 self.assertRaises(TypeError, connection.accept, None)
2223
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002224 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002225 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002226 :py:obj:`Connection.accept` accepts a pending connection attempt and
2227 returns a tuple of a new :py:obj:`Connection` (the accepted client) and
2228 the address the connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002229 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002230 ctx = Context(TLSv1_METHOD)
2231 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2232 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002233 port = socket()
2234 portSSL = Connection(ctx, port)
2235 portSSL.bind(('', 0))
2236 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002237
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002238 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002239
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002240 # Calling portSSL.getsockname() here to get the server IP address
2241 # sounds great, but frequently fails on Windows.
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002242 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002243
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002244 serverSSL, address = portSSL.accept()
2245
2246 self.assertTrue(isinstance(serverSSL, Connection))
2247 self.assertIdentical(serverSSL.get_context(), ctx)
2248 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002249
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002250 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002251 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002252 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with
2253 the wrong number of arguments or with arguments other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002254 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002255 connection = Connection(Context(TLSv1_METHOD), None)
2256 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04002257 self.assertRaises(TypeError, connection.get_shutdown, None)
2258 self.assertRaises(TypeError, connection.set_shutdown)
2259 self.assertRaises(TypeError, connection.set_shutdown, None)
2260 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002261
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002262 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002263 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002264 :py:obj:`Connection.shutdown` performs an SSL-level connection
2265 shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002266 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002267 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002268 self.assertFalse(server.shutdown())
2269 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002270 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002271 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
2272 client.shutdown()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002273 self.assertEquals(
2274 client.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN
2275 )
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002276 self.assertRaises(ZeroReturnError, server.recv, 1024)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002277 self.assertEquals(
2278 server.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN
2279 )
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002280
Paul Aurichc85e0862015-01-08 08:34:33 -08002281 def test_shutdown_closed(self):
2282 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002283 If the underlying socket is closed, :py:obj:`Connection.shutdown`
2284 propagates the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002285 """
2286 server, client = self._loopback()
2287 server.sock_shutdown(2)
2288 exc = self.assertRaises(SysCallError, server.shutdown)
2289 if platform == "win32":
2290 self.assertEqual(exc.args[0], ESHUTDOWN)
2291 else:
2292 self.assertEqual(exc.args[0], EPIPE)
2293
Glyph89389472015-04-14 17:29:26 -04002294 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002295 """
Glyph89389472015-04-14 17:29:26 -04002296 If the underlying connection is truncated, :obj:`Connection.shutdown`
2297 raises an :obj:`Error`.
Glyph6064ec32015-04-14 16:38:22 -04002298 """
Glyph89389472015-04-14 17:29:26 -04002299 server_ctx = Context(TLSv1_METHOD)
2300 client_ctx = Context(TLSv1_METHOD)
2301 server_ctx.use_privatekey(
2302 load_privatekey(FILETYPE_PEM, server_key_pem))
2303 server_ctx.use_certificate(
2304 load_certificate(FILETYPE_PEM, server_cert_pem))
2305 server = Connection(server_ctx, None)
2306 client = Connection(client_ctx, None)
2307 self._handshakeInMemory(client, server)
2308 self.assertEqual(server.shutdown(), False)
2309 self.assertRaises(WantReadError, server.shutdown)
2310 server.bio_shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002311 self.assertRaises(Error, server.shutdown)
2312
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002313 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002314 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002315 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection
2316 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002317 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002318 connection = Connection(Context(TLSv1_METHOD), socket())
2319 connection.set_shutdown(RECEIVED_SHUTDOWN)
2320 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2321
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002322 @skip_if_py3
2323 def test_set_shutdown_long(self):
2324 """
2325 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
2326 of type :py:obj:`long` as well as :py:obj:`int`.
2327 """
2328 connection = Connection(Context(TLSv1_METHOD), socket())
2329 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
2330 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002331
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002332 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002333 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002334 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called
2335 with other than one argument. :py:obj:`Connection.get_app_data` raises
2336 :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002337 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002338 conn = Connection(Context(TLSv1_METHOD), None)
2339 self.assertRaises(TypeError, conn.get_app_data, None)
2340 self.assertRaises(TypeError, conn.set_app_data)
2341 self.assertRaises(TypeError, conn.set_app_data, None, None)
2342
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002343 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002344 """
2345 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002346 :py:obj:`Connection.set_app_data` and later retrieved with
2347 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002348 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002349 conn = Connection(Context(TLSv1_METHOD), None)
2350 app_data = object()
2351 conn.set_app_data(app_data)
2352 self.assertIdentical(conn.get_app_data(), app_data)
2353
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002354 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002355 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002356 :py:obj:`Connection.makefile` is not implemented and calling that
2357 method raises :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002358 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002359 conn = Connection(Context(TLSv1_METHOD), None)
2360 self.assertRaises(NotImplementedError, conn.makefile)
2361
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002362 def test_get_peer_cert_chain_wrong_args(self):
2363 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002364 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if
2365 called with any arguments.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002366 """
2367 conn = Connection(Context(TLSv1_METHOD), None)
2368 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
2369 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
2370 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
2371 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
2372
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002373 def test_get_peer_cert_chain(self):
2374 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002375 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates
2376 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002377 """
2378 chain = _create_certificate_chain()
2379 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2380
2381 serverContext = Context(TLSv1_METHOD)
2382 serverContext.use_privatekey(skey)
2383 serverContext.use_certificate(scert)
2384 serverContext.add_extra_chain_cert(icert)
2385 serverContext.add_extra_chain_cert(cacert)
2386 server = Connection(serverContext, None)
2387 server.set_accept_state()
2388
2389 # Create the client
2390 clientContext = Context(TLSv1_METHOD)
2391 clientContext.set_verify(VERIFY_NONE, verify_cb)
2392 client = Connection(clientContext, None)
2393 client.set_connect_state()
2394
2395 self._interactInMemory(client, server)
2396
2397 chain = client.get_peer_cert_chain()
2398 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002399 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002400 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002401 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002402 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002403 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002404 "Authority Certificate", chain[2].get_subject().CN)
2405
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002406 def test_get_peer_cert_chain_none(self):
2407 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002408 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the
2409 peer sends no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002410 """
2411 ctx = Context(TLSv1_METHOD)
2412 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2413 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2414 server = Connection(ctx, None)
2415 server.set_accept_state()
2416 client = Connection(Context(TLSv1_METHOD), None)
2417 client.set_connect_state()
2418 self._interactInMemory(client, server)
2419 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002420
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002421 def test_get_session_wrong_args(self):
2422 """
2423 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
2424 with any arguments.
2425 """
2426 ctx = Context(TLSv1_METHOD)
2427 server = Connection(ctx, None)
2428 self.assertRaises(TypeError, server.get_session, 123)
2429 self.assertRaises(TypeError, server.get_session, "hello")
2430 self.assertRaises(TypeError, server.get_session, object())
2431
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002432 def test_get_session_unconnected(self):
2433 """
2434 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
2435 an object which has not been connected.
2436 """
2437 ctx = Context(TLSv1_METHOD)
2438 server = Connection(ctx, None)
2439 session = server.get_session()
2440 self.assertIdentical(None, session)
2441
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002442 def test_server_get_session(self):
2443 """
2444 On the server side of a connection, :py:obj:`Connection.get_session`
2445 returns a :py:class:`Session` instance representing the SSL session for
2446 that connection.
2447 """
2448 server, client = self._loopback()
2449 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002450 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002451
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002452 def test_client_get_session(self):
2453 """
2454 On the client side of a connection, :py:obj:`Connection.get_session`
2455 returns a :py:class:`Session` instance representing the SSL session for
2456 that connection.
2457 """
2458 server, client = self._loopback()
2459 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002460 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002461
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002462 def test_set_session_wrong_args(self):
2463 """
2464 If called with an object that is not an instance of :py:class:`Session`,
2465 or with other than one argument, :py:obj:`Connection.set_session` raises
2466 :py:obj:`TypeError`.
2467 """
2468 ctx = Context(TLSv1_METHOD)
2469 connection = Connection(ctx, None)
2470 self.assertRaises(TypeError, connection.set_session)
2471 self.assertRaises(TypeError, connection.set_session, 123)
2472 self.assertRaises(TypeError, connection.set_session, "hello")
2473 self.assertRaises(TypeError, connection.set_session, object())
2474 self.assertRaises(
2475 TypeError, connection.set_session, Session(), Session())
2476
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002477 def test_client_set_session(self):
2478 """
2479 :py:obj:`Connection.set_session`, when used prior to a connection being
2480 established, accepts a :py:class:`Session` instance and causes an
2481 attempt to re-use the session it represents when the SSL handshake is
2482 performed.
2483 """
2484 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2485 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2486 ctx = Context(TLSv1_METHOD)
2487 ctx.use_privatekey(key)
2488 ctx.use_certificate(cert)
2489 ctx.set_session_id("unity-test")
2490
2491 def makeServer(socket):
2492 server = Connection(ctx, socket)
2493 server.set_accept_state()
2494 return server
2495
2496 originalServer, originalClient = self._loopback(
2497 serverFactory=makeServer)
2498 originalSession = originalClient.get_session()
2499
2500 def makeClient(socket):
2501 client = self._loopbackClientFactory(socket)
2502 client.set_session(originalSession)
2503 return client
2504 resumedServer, resumedClient = self._loopback(
2505 serverFactory=makeServer,
2506 clientFactory=makeClient)
2507
2508 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002509 # identifier for the session (new enough versions of OpenSSL expose
2510 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002511 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002512 # session is re-used. As long as the master key for the two
2513 # connections is the same, the session was re-used!
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002514 self.assertEqual(
2515 originalServer.master_key(), resumedServer.master_key())
2516
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002517 def test_set_session_wrong_method(self):
2518 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002519 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002520 instance associated with a context using a different SSL method than
2521 the :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002522 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002523 """
2524 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2525 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2526 ctx = Context(TLSv1_METHOD)
2527 ctx.use_privatekey(key)
2528 ctx.use_certificate(cert)
2529 ctx.set_session_id("unity-test")
2530
2531 def makeServer(socket):
2532 server = Connection(ctx, socket)
2533 server.set_accept_state()
2534 return server
2535
2536 originalServer, originalClient = self._loopback(
2537 serverFactory=makeServer)
2538 originalSession = originalClient.get_session()
2539
2540 def makeClient(socket):
2541 # Intentionally use a different, incompatible method here.
2542 client = Connection(Context(SSLv3_METHOD), socket)
2543 client.set_connect_state()
2544 client.set_session(originalSession)
2545 return client
2546
2547 self.assertRaises(
2548 Error,
2549 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2550
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002551 def test_wantWriteError(self):
2552 """
2553 :py:obj:`Connection` methods which generate output raise
2554 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2555 fail indicating a should-write state.
2556 """
2557 client_socket, server_socket = socket_pair()
2558 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002559 # anything. Only write a single byte at a time so we can be sure we
2560 # completely fill the buffer. Even though the socket API is allowed to
2561 # signal a short write via its return value it seems this doesn't
2562 # always happen on all platforms (FreeBSD and OS X particular) for the
2563 # very last bit of available buffer space.
2564 msg = b"x"
2565 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002566 try:
2567 client_socket.send(msg)
2568 except error as e:
2569 if e.errno == EWOULDBLOCK:
2570 break
2571 raise
2572 else:
2573 self.fail(
2574 "Failed to fill socket buffer, cannot test BIO want write")
2575
2576 ctx = Context(TLSv1_METHOD)
2577 conn = Connection(ctx, client_socket)
2578 # Client's speak first, so make it an SSL client
2579 conn.set_connect_state()
2580 self.assertRaises(WantWriteError, conn.do_handshake)
2581
2582 # XXX want_read
2583
Fedor Brunner416f4a12014-03-28 13:18:38 +01002584 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002585 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002586 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2587 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002588 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002589 ctx = Context(TLSv1_METHOD)
2590 connection = Connection(ctx, None)
2591 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002592
2593 def test_get_peer_finished_before_connect(self):
2594 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002595 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2596 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002597 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002598 ctx = Context(TLSv1_METHOD)
2599 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002600 self.assertEqual(connection.get_peer_finished(), None)
2601
Fedor Brunner416f4a12014-03-28 13:18:38 +01002602 def test_get_finished(self):
2603 """
2604 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002605 message send from client, or server. Finished messages are send during
2606 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002607 """
2608
Fedor Brunner5747b932014-03-05 14:22:34 +01002609 server, client = self._loopback()
2610
2611 self.assertNotEqual(server.get_finished(), None)
2612 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002613
2614 def test_get_peer_finished(self):
2615 """
2616 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002617 message received from client, or server. Finished messages are send
2618 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002619 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002620 server, client = self._loopback()
2621
2622 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002623 self.assertTrue(len(server.get_peer_finished()) > 0)
2624
Fedor Brunner416f4a12014-03-28 13:18:38 +01002625 def test_tls_finished_message_symmetry(self):
2626 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002627 The TLS Finished message send by server must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002628 received by client.
2629
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002630 The TLS Finished message send by client must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002631 received by server.
2632 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002633 server, client = self._loopback()
2634
Fedor Brunner5747b932014-03-05 14:22:34 +01002635 self.assertEqual(server.get_finished(), client.get_peer_finished())
2636 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002637
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002638 def test_get_cipher_name_before_connect(self):
2639 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002640 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2641 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002642 """
2643 ctx = Context(TLSv1_METHOD)
2644 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002645 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002646
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002647 def test_get_cipher_name(self):
2648 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002649 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2650 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002651 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002652 server, client = self._loopback()
2653 server_cipher_name, client_cipher_name = \
2654 server.get_cipher_name(), client.get_cipher_name()
2655
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002656 self.assertIsInstance(server_cipher_name, text_type)
2657 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002658
2659 self.assertEqual(server_cipher_name, client_cipher_name)
2660
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002661 def test_get_cipher_version_before_connect(self):
2662 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002663 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2664 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002665 """
2666 ctx = Context(TLSv1_METHOD)
2667 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002668 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002669
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002670 def test_get_cipher_version(self):
2671 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002672 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2673 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002674 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002675 server, client = self._loopback()
2676 server_cipher_version, client_cipher_version = \
2677 server.get_cipher_version(), client.get_cipher_version()
2678
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002679 self.assertIsInstance(server_cipher_version, text_type)
2680 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002681
2682 self.assertEqual(server_cipher_version, client_cipher_version)
2683
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002684 def test_get_cipher_bits_before_connect(self):
2685 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002686 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2687 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002688 """
2689 ctx = Context(TLSv1_METHOD)
2690 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002691 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002692
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002693 def test_get_cipher_bits(self):
2694 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002695 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2696 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002697 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002698 server, client = self._loopback()
2699 server_cipher_bits, client_cipher_bits = \
2700 server.get_cipher_bits(), client.get_cipher_bits()
2701
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002702 self.assertIsInstance(server_cipher_bits, int)
2703 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002704
2705 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002706
Jim Shaverabff1882015-05-27 09:15:55 -04002707 def test_get_protocol_version_name(self):
2708 """
2709 :py:obj:`Connection.get_protocol_version_name()` returns a string
2710 giving the protocol version of the current connection.
2711 """
2712 server, client = self._loopback()
2713 client_protocol_version_name = client.get_protocol_version_name()
2714 server_protocol_version_name = server.get_protocol_version_name()
2715
Jim Shaver58d25732015-05-28 11:52:32 -04002716 self.assertIsInstance(server_protocol_version_name, text_type)
2717 self.assertIsInstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002718
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002719 self.assertEqual(
2720 server_protocol_version_name, client_protocol_version_name
2721 )
Jim Shaverabff1882015-05-27 09:15:55 -04002722
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002723 def test_get_protocol_version(self):
2724 """
Alex Gaynor43307782015-09-04 09:05:45 -04002725 :py:obj:`Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002726 giving the protocol version of the current connection.
2727 """
2728 server, client = self._loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002729 client_protocol_version = client.get_protocol_version()
2730 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002731
Jim Shaverabff1882015-05-27 09:15:55 -04002732 self.assertIsInstance(server_protocol_version, int)
2733 self.assertIsInstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002734
2735 self.assertEqual(server_protocol_version, client_protocol_version)
2736
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002737
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002738class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002739 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002740 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002741 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002742 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002743 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002744 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002745 arguments.
2746 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002747 connection = Connection(Context(TLSv1_METHOD), None)
2748 self.assertRaises(TypeError, connection.get_cipher_list, None)
2749
2750
2751 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002752 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002753 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2754 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002755 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002756 connection = Connection(Context(TLSv1_METHOD), None)
2757 ciphers = connection.get_cipher_list()
2758 self.assertTrue(isinstance(ciphers, list))
2759 for cipher in ciphers:
2760 self.assertTrue(isinstance(cipher, str))
2761
2762
2763
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002764class ConnectionSendTests(TestCase, _LoopbackMixin):
2765 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002766 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002767 """
2768 def test_wrong_args(self):
2769 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002770 When called with arguments other than string argument for its first
2771 parameter or more than two arguments, :py:obj:`Connection.send` raises
2772 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002773 """
2774 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002775 self.assertRaises(TypeError, connection.send)
2776 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002777 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002778
2779
2780 def test_short_bytes(self):
2781 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002782 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002783 and returns the number of bytes sent.
2784 """
2785 server, client = self._loopback()
2786 count = server.send(b('xy'))
2787 self.assertEquals(count, 2)
2788 self.assertEquals(client.recv(2), b('xy'))
2789
Abraham Martinef063482015-03-25 14:06:24 +00002790
2791 def test_text(self):
2792 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002793 When passed a text, :py:obj:`Connection.send` transmits all of it and
2794 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002795 """
2796 server, client = self._loopback()
2797 with catch_warnings(record=True) as w:
2798 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002799 count = server.send(b"xy".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002800 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002801 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002802 WARNING_TYPE_EXPECTED
2803 ),
2804 str(w[-1].message)
2805 )
2806 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinef063482015-03-25 14:06:24 +00002807 self.assertEquals(count, 2)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002808 self.assertEquals(client.recv(2), b"xy")
Abraham Martinef063482015-03-25 14:06:24 +00002809
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002810 try:
2811 memoryview
2812 except NameError:
2813 "cannot test sending memoryview without memoryview"
2814 else:
2815 def test_short_memoryview(self):
2816 """
2817 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002818 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002819 bytes sent.
2820 """
2821 server, client = self._loopback()
2822 count = server.send(memoryview(b('xy')))
2823 self.assertEquals(count, 2)
2824 self.assertEquals(client.recv(2), b('xy'))
2825
2826
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002827 try:
2828 buffer
2829 except NameError:
2830 "cannot test sending buffer without buffer"
2831 else:
2832 def test_short_buffer(self):
2833 """
2834 When passed a buffer containing a small number of bytes,
2835 :py:obj:`Connection.send` transmits all of them and returns the number of
2836 bytes sent.
2837 """
2838 server, client = self._loopback()
2839 count = server.send(buffer(b('xy')))
2840 self.assertEquals(count, 2)
2841 self.assertEquals(client.recv(2), b('xy'))
2842
2843
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002844
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002845def _make_memoryview(size):
2846 """
2847 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2848 size.
2849 """
2850 return memoryview(bytearray(size))
2851
2852
2853
Cory Benfield62d10332014-06-15 10:03:41 +01002854class ConnectionRecvIntoTests(TestCase, _LoopbackMixin):
2855 """
2856 Tests for :py:obj:`Connection.recv_into`
2857 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002858 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002859 """
2860 Assert that when the given buffer is passed to
2861 ``Connection.recv_into``, whatever bytes are available to be received
2862 that fit into that buffer are written into that buffer.
2863 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002864 output_buffer = factory(5)
2865
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002866 server, client = self._loopback()
2867 server.send(b('xy'))
2868
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002869 self.assertEqual(client.recv_into(output_buffer), 2)
2870 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002871
2872
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002873 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002874 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002875 :py:obj:`Connection.recv_into` can be passed a ``bytearray`` instance
2876 and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002877 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002878 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002879
2880
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002881 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002882 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002883 Assert that when the given buffer is passed to ``Connection.recv_into``
2884 along with a value for ``nbytes`` that is less than the size of that
2885 buffer, only ``nbytes`` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002886 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002887 output_buffer = factory(10)
2888
Cory Benfield62d10332014-06-15 10:03:41 +01002889 server, client = self._loopback()
2890 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002891
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002892 self.assertEqual(client.recv_into(output_buffer, 5), 5)
2893 self.assertEqual(
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002894 output_buffer, bytearray(b('abcde\x00\x00\x00\x00\x00'))
2895 )
2896
2897
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002898 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002899 """
2900 When called with a ``bytearray`` instance,
2901 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter and
2902 doesn't copy in more than that number of bytes.
2903 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002904 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002905
2906
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002907 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002908 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002909 Assert that if there are more bytes available to be read from the
2910 receive buffer than would fit into the buffer passed to
2911 :py:obj:`Connection.recv_into`, only as many as fit are written into
2912 it.
Cory Benfield62d10332014-06-15 10:03:41 +01002913 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002914 output_buffer = factory(5)
2915
Cory Benfield62d10332014-06-15 10:03:41 +01002916 server, client = self._loopback()
2917 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002918
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002919 self.assertEqual(client.recv_into(output_buffer), 5)
2920 self.assertEqual(output_buffer, bytearray(b('abcde')))
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002921 rest = client.recv(5)
2922 self.assertEqual(b('fghij'), rest)
2923
2924
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002925 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002926 """
2927 When called with a ``bytearray`` instance,
2928 :py:obj:`Connection.recv_into` respects the size of the array and
2929 doesn't write more bytes into it than will fit.
2930 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002931 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002932
2933
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002934 def _really_doesnt_overfill_test(self, factory):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002935 """
2936 Assert that if the value given by ``nbytes`` is greater than the actual
2937 size of the output buffer passed to :py:obj:`Connection.recv_into`, the
2938 behavior is as if no value was given for ``nbytes`` at all.
2939 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002940 output_buffer = factory(5)
2941
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002942 server, client = self._loopback()
2943 server.send(b('abcdefghij'))
2944
2945 self.assertEqual(client.recv_into(output_buffer, 50), 5)
2946 self.assertEqual(output_buffer, bytearray(b('abcde')))
2947 rest = client.recv(5)
2948 self.assertEqual(b('fghij'), rest)
2949
2950
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002951 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002952 """
2953 When called with a ``bytearray`` instance and an ``nbytes`` value that
2954 is too large, :py:obj:`Connection.recv_into` respects the size of the
2955 array and not the ``nbytes`` value and doesn't write more bytes into
2956 the buffer than will fit.
2957 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002958 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002959
2960
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002961 def test_peek(self):
2962
2963 server, client = self._loopback()
2964 server.send(b('xy'))
2965
2966 for _ in range(2):
2967 output_buffer = bytearray(5)
2968 self.assertEqual(client.recv_into(output_buffer, flags=MSG_PEEK), 2)
2969 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
2970
2971
Cory Benfield62d10332014-06-15 10:03:41 +01002972 try:
2973 memoryview
2974 except NameError:
2975 "cannot test recv_into memoryview without memoryview"
2976 else:
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002977 def test_memoryview_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002978 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002979 :py:obj:`Connection.recv_into` can be passed a ``memoryview``
2980 instance and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002981 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002982 self._no_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002983
2984
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002985 def test_memoryview_respects_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002986 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002987 When called with a ``memoryview`` instance,
2988 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter
2989 and doesn't copy more than that number of bytes in.
Cory Benfield62d10332014-06-15 10:03:41 +01002990 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002991 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002992
2993
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002994 def test_memoryview_doesnt_overfill(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002995 """
Jean-Paul Calderone8fd82552015-03-15 17:21:07 -04002996 When called with a ``memoryview`` instance,
2997 :py:obj:`Connection.recv_into` respects the size of the array and
2998 doesn't write more bytes into it than will fit.
Cory Benfield62d10332014-06-15 10:03:41 +01002999 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003000 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003001
3002
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003003 def test_memoryview_really_doesnt_overfill(self):
3004 """
3005 When called with a ``memoryview`` instance and an ``nbytes`` value
3006 that is too large, :py:obj:`Connection.recv_into` respects the size
3007 of the array and not the ``nbytes`` value and doesn't write more
3008 bytes into the buffer than will fit.
3009 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003010 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003011
3012
Cory Benfield62d10332014-06-15 10:03:41 +01003013
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003014class ConnectionSendallTests(TestCase, _LoopbackMixin):
3015 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003016 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003017 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003018 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003019 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003020 When called with arguments other than a string argument for its first
3021 parameter or with more than two arguments, :py:obj:`Connection.sendall`
3022 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003023 """
3024 connection = Connection(Context(TLSv1_METHOD), None)
3025 self.assertRaises(TypeError, connection.sendall)
3026 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003027 self.assertRaises(
3028 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003029
3030
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003031 def test_short(self):
3032 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003033 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003034 it.
3035 """
3036 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04003037 server.sendall(b('x'))
3038 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003039
3040
Abraham Martinef063482015-03-25 14:06:24 +00003041 def test_text(self):
3042 """
Jean-Paul Calderone93477422015-04-13 20:38:57 -04003043 :py:obj:`Connection.sendall` transmits all the content in the string
3044 passed to it raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003045 """
3046 server, client = self._loopback()
3047 with catch_warnings(record=True) as w:
3048 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003049 server.sendall(b"x".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003050 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003051 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003052 WARNING_TYPE_EXPECTED
3053 ),
3054 str(w[-1].message)
3055 )
3056 self.assertIs(w[-1].category, DeprecationWarning)
3057 self.assertEquals(client.recv(1), b"x")
Abraham Martinef063482015-03-25 14:06:24 +00003058
3059
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003060 try:
3061 memoryview
3062 except NameError:
3063 "cannot test sending memoryview without memoryview"
3064 else:
3065 def test_short_memoryview(self):
3066 """
3067 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003068 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003069 """
3070 server, client = self._loopback()
3071 server.sendall(memoryview(b('x')))
3072 self.assertEquals(client.recv(1), b('x'))
3073
3074
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003075 try:
3076 buffer
3077 except NameError:
3078 "cannot test sending buffers without buffers"
3079 else:
3080 def test_short_buffers(self):
3081 """
3082 When passed a buffer containing a small number of bytes,
3083 :py:obj:`Connection.sendall` transmits all of them.
3084 """
3085 server, client = self._loopback()
3086 server.sendall(buffer(b('x')))
3087 self.assertEquals(client.recv(1), b('x'))
3088
3089
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003090 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003091 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003092 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003093 it even if this requires multiple calls of an underlying write function.
3094 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003095 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003096 # Should be enough, underlying SSL_write should only do 16k at a time.
3097 # On Windows, after 32k of bytes the write will block (forever - because
3098 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04003099 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003100 server.sendall(message)
3101 accum = []
3102 received = 0
3103 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003104 data = client.recv(1024)
3105 accum.append(data)
3106 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04003107 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003108
3109
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003110 def test_closed(self):
3111 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003112 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003113 write error from the low level write call.
3114 """
3115 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003116 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003117 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003118 if platform == "win32":
3119 self.assertEqual(exc.args[0], ESHUTDOWN)
3120 else:
3121 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003122
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003123
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04003124
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003125class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
3126 """
3127 Tests for SSL renegotiation APIs.
3128 """
3129 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003130 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003131 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003132 arguments.
3133 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003134 connection = Connection(Context(TLSv1_METHOD), None)
3135 self.assertRaises(TypeError, connection.renegotiate, None)
3136
3137
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003138 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003139 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003140 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003141 any arguments.
3142 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003143 connection = Connection(Context(TLSv1_METHOD), None)
3144 self.assertRaises(TypeError, connection.total_renegotiations, None)
3145
3146
3147 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003148 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003149 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003150 renegotiations have happened.
3151 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003152 connection = Connection(Context(TLSv1_METHOD), None)
3153 self.assertEquals(connection.total_renegotiations(), 0)
3154
3155
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003156# def test_renegotiate(self):
3157# """
3158# """
3159# server, client = self._loopback()
3160
3161# server.send("hello world")
3162# self.assertEquals(client.recv(len("hello world")), "hello world")
3163
3164# self.assertEquals(server.total_renegotiations(), 0)
3165# self.assertTrue(server.renegotiate())
3166
3167# server.setblocking(False)
3168# client.setblocking(False)
3169# while server.renegotiate_pending():
3170# client.do_handshake()
3171# server.do_handshake()
3172
3173# self.assertEquals(server.total_renegotiations(), 1)
3174
3175
3176
3177
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003178class ErrorTests(TestCase):
3179 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003180 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003181 """
3182 def test_type(self):
3183 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003184 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003185 """
3186 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05003187 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05003188
3189
3190
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003191class ConstantsTests(TestCase):
3192 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003193 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003194
3195 These are values defined by OpenSSL intended only to be used as flags to
3196 OpenSSL APIs. The only assertions it seems can be made about them is
3197 their values.
3198 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003199 # unittest.TestCase has no skip mechanism
3200 if OP_NO_QUERY_MTU is not None:
3201 def test_op_no_query_mtu(self):
3202 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003203 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003204 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003205 """
3206 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
3207 else:
3208 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003209
3210
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003211 if OP_COOKIE_EXCHANGE is not None:
3212 def test_op_cookie_exchange(self):
3213 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003214 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003215 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003216 """
3217 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
3218 else:
3219 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003220
3221
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003222 if OP_NO_TICKET is not None:
3223 def test_op_no_ticket(self):
3224 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003225 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003226 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003227 """
3228 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04003229 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003230 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05003231
3232
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003233 if OP_NO_COMPRESSION is not None:
3234 def test_op_no_compression(self):
3235 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003236 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
3237 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003238 """
3239 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
3240 else:
3241 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3242
3243
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003244 def test_sess_cache_off(self):
3245 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003246 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3247 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003248 """
3249 self.assertEqual(0x0, SESS_CACHE_OFF)
3250
3251
3252 def test_sess_cache_client(self):
3253 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003254 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3255 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003256 """
3257 self.assertEqual(0x1, SESS_CACHE_CLIENT)
3258
3259
3260 def test_sess_cache_server(self):
3261 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003262 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3263 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003264 """
3265 self.assertEqual(0x2, SESS_CACHE_SERVER)
3266
3267
3268 def test_sess_cache_both(self):
3269 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003270 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3271 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003272 """
3273 self.assertEqual(0x3, SESS_CACHE_BOTH)
3274
3275
3276 def test_sess_cache_no_auto_clear(self):
3277 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003278 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3279 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3280 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003281 """
3282 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
3283
3284
3285 def test_sess_cache_no_internal_lookup(self):
3286 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003287 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3288 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3289 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003290 """
3291 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
3292
3293
3294 def test_sess_cache_no_internal_store(self):
3295 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003296 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3297 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3298 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003299 """
3300 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
3301
3302
3303 def test_sess_cache_no_internal(self):
3304 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003305 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3306 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
3307 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003308 """
3309 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
3310
3311
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04003312
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003313class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05003314 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003315 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003316 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003317 def _server(self, sock):
3318 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003319 Create a new server-side SSL :py:obj:`Connection` object wrapped around
3320 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003321 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003322 # Create the server side Connection. This is mostly setup boilerplate
3323 # - use TLSv1, use a particular certificate, etc.
3324 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003325 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
3326 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 -04003327 server_store = server_ctx.get_cert_store()
3328 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3329 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3330 server_ctx.check_privatekey()
3331 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003332 # Here the Connection is actually created. If None is passed as the 2nd
3333 # parameter, it indicates a memory BIO should be created.
3334 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003335 server_conn.set_accept_state()
3336 return server_conn
3337
3338
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003339 def _client(self, sock):
3340 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003341 Create a new client-side SSL :py:obj:`Connection` object wrapped around
3342 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003343 """
3344 # Now create the client side Connection. Similar boilerplate to the
3345 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003346 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003347 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
3348 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 -04003349 client_store = client_ctx.get_cert_store()
3350 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
3351 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
3352 client_ctx.check_privatekey()
3353 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003354 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003355 client_conn.set_connect_state()
3356 return client_conn
3357
3358
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003359 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003360 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003361 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003362 reading from the output of each and writing those bytes to the input of
3363 the other and in this way establish a connection and exchange
3364 application-level bytes with each other.
3365 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003366 server_conn = self._server(None)
3367 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003368
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003369 # There should be no key or nonces yet.
3370 self.assertIdentical(server_conn.master_key(), None)
3371 self.assertIdentical(server_conn.client_random(), None)
3372 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003373
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003374 # First, the handshake needs to happen. We'll deliver bytes back and
3375 # forth between the client and server until neither of them feels like
3376 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003377 self.assertIdentical(
3378 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003379
3380 # Now that the handshake is done, there should be a key and nonces.
3381 self.assertNotIdentical(server_conn.master_key(), None)
3382 self.assertNotIdentical(server_conn.client_random(), None)
3383 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04003384 self.assertEquals(server_conn.client_random(), client_conn.client_random())
3385 self.assertEquals(server_conn.server_random(), client_conn.server_random())
3386 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
3387 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003388
3389 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003390 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05003391
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003392 server_conn.write(important_message)
3393 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003394 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003395 (client_conn, important_message))
3396
3397 client_conn.write(important_message[::-1])
3398 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003399 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003400 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003401
3402
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003403 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003404 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003405 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003406
3407 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09003408 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003409 this test fails, there must be a problem outside the memory BIO
3410 code, as no memory BIO is involved here). Even though this isn't a
3411 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003412 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04003413 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003414
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003415 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05003416 client_conn.send(important_message)
3417 msg = server_conn.recv(1024)
3418 self.assertEqual(msg, important_message)
3419
3420 # Again in the other direction, just for fun.
3421 important_message = important_message[::-1]
3422 server_conn.send(important_message)
3423 msg = client_conn.recv(1024)
3424 self.assertEqual(msg, important_message)
3425
3426
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04003427 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003428 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003429 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
3430 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003431 """
3432 context = Context(SSLv3_METHOD)
3433 client = socket()
3434 clientSSL = Connection(context, client)
Alex Gaynor43307782015-09-04 09:05:45 -04003435 self.assertRaises(TypeError, clientSSL.bio_read, 100)
3436 self.assertRaises(TypeError, clientSSL.bio_write, "foo")
Alex Gaynor7e8b61e2015-09-04 13:13:05 -04003437 self.assertRaises(TypeError, clientSSL.bio_shutdown)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003438
3439
3440 def test_outgoingOverflow(self):
3441 """
3442 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09003443 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003444 returned and that many bytes from the beginning of the input can be
3445 read from the other end of the connection.
3446 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003447 server = self._server(None)
3448 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003449
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003450 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003451
3452 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003453 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003454 # Sanity check. We're trying to test what happens when the entire
3455 # input can't be sent. If the entire input was sent, this test is
3456 # meaningless.
3457 self.assertTrue(sent < size)
3458
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003459 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003460 self.assertIdentical(receiver, server)
3461
3462 # We can rely on all of these bytes being received at once because
3463 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
3464 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003465
3466
3467 def test_shutdown(self):
3468 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003469 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
3470 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003471 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003472 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003473 server.bio_shutdown()
3474 e = self.assertRaises(Error, server.recv, 1024)
3475 # We don't want WantReadError or ZeroReturnError or anything - it's a
3476 # handshake failure.
3477 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003478
3479
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003480 def test_unexpectedEndOfFile(self):
3481 """
3482 If the connection is lost before an orderly SSL shutdown occurs,
3483 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
3484 "Unexpected EOF".
3485 """
3486 server_conn, client_conn = self._loopback()
3487 client_conn.sock_shutdown(SHUT_RDWR)
3488 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
3489 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
3490
3491
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003492 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003493 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003494 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 -04003495
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003496 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003497 before the client and server are connected to each other. This
3498 function should specify a list of CAs for the server to send to the
3499 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09003500 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003501 times.
3502 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003503 server = self._server(None)
3504 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003505 self.assertEqual(client.get_client_ca_list(), [])
3506 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003507 ctx = server.get_context()
3508 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003509 self.assertEqual(client.get_client_ca_list(), [])
3510 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003511 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003512 self.assertEqual(client.get_client_ca_list(), expected)
3513 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003514
3515
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003516 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003517 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003518 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003519 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003520 """
3521 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003522 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
3523 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
3524 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003525
3526
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003527 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003528 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003529 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003530 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09003531 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003532 after the connection is set up.
3533 """
3534 def no_ca(ctx):
3535 ctx.set_client_ca_list([])
3536 return []
3537 self._check_client_ca_list(no_ca)
3538
3539
3540 def test_set_one_ca_list(self):
3541 """
3542 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003543 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003544 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003545 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003546 X509Name after the connection is set up.
3547 """
3548 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3549 cadesc = cacert.get_subject()
3550 def single_ca(ctx):
3551 ctx.set_client_ca_list([cadesc])
3552 return [cadesc]
3553 self._check_client_ca_list(single_ca)
3554
3555
3556 def test_set_multiple_ca_list(self):
3557 """
3558 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003559 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003560 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003561 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003562 X509Names after the connection is set up.
3563 """
3564 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3565 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3566
3567 sedesc = secert.get_subject()
3568 cldesc = clcert.get_subject()
3569
3570 def multiple_ca(ctx):
3571 L = [sedesc, cldesc]
3572 ctx.set_client_ca_list(L)
3573 return L
3574 self._check_client_ca_list(multiple_ca)
3575
3576
3577 def test_reset_ca_list(self):
3578 """
3579 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09003580 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003581 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003582 """
3583 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3584 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3585 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3586
3587 cadesc = cacert.get_subject()
3588 sedesc = secert.get_subject()
3589 cldesc = clcert.get_subject()
3590
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003591 def changed_ca(ctx):
3592 ctx.set_client_ca_list([sedesc, cldesc])
3593 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003594 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003595 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003596
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003597
3598 def test_mutated_ca_list(self):
3599 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003600 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003601 afterwards, this does not affect the list of CA names sent to the
3602 client.
3603 """
3604 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3605 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3606
3607 cadesc = cacert.get_subject()
3608 sedesc = secert.get_subject()
3609
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003610 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003611 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003612 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003613 L.append(sedesc)
3614 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003615 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003616
3617
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003618 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003619 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003620 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003621 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003622 """
3623 ctx = Context(TLSv1_METHOD)
3624 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003625 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003626 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003627 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003628
3629
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003630 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003631 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003632 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09003633 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003634 """
3635 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3636 cadesc = cacert.get_subject()
3637 def single_ca(ctx):
3638 ctx.add_client_ca(cacert)
3639 return [cadesc]
3640 self._check_client_ca_list(single_ca)
3641
3642
3643 def test_multiple_add_client_ca(self):
3644 """
3645 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09003646 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003647 """
3648 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3649 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3650
3651 cadesc = cacert.get_subject()
3652 sedesc = secert.get_subject()
3653
3654 def multiple_ca(ctx):
3655 ctx.add_client_ca(cacert)
3656 ctx.add_client_ca(secert)
3657 return [cadesc, sedesc]
3658 self._check_client_ca_list(multiple_ca)
3659
3660
3661 def test_set_and_add_client_ca(self):
3662 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003663 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
3664 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003665 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003666 """
3667 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3668 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3669 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3670
3671 cadesc = cacert.get_subject()
3672 sedesc = secert.get_subject()
3673 cldesc = clcert.get_subject()
3674
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003675 def mixed_set_add_ca(ctx):
3676 ctx.set_client_ca_list([cadesc, sedesc])
3677 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003678 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003679 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003680
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003681
3682 def test_set_after_add_client_ca(self):
3683 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003684 A call to :py:obj:`Context.set_client_ca_list` after a call to
3685 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003686 call with the names specified by the latter cal.
3687 """
3688 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3689 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3690 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3691
3692 cadesc = cacert.get_subject()
3693 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003694
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003695 def set_replaces_add_ca(ctx):
3696 ctx.add_client_ca(clcert)
3697 ctx.set_client_ca_list([cadesc])
3698 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003699 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003700 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003701
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003702
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003703
3704class ConnectionBIOTests(TestCase):
3705 """
3706 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3707 """
3708 def test_wantReadError(self):
3709 """
3710 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
3711 if there are no bytes available to be read from the BIO.
3712 """
3713 ctx = Context(TLSv1_METHOD)
3714 conn = Connection(ctx, None)
3715 self.assertRaises(WantReadError, conn.bio_read, 1024)
3716
3717
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003718 def test_buffer_size(self):
3719 """
3720 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3721 number of bytes to read and return.
3722 """
3723 ctx = Context(TLSv1_METHOD)
3724 conn = Connection(ctx, None)
3725 conn.set_connect_state()
3726 try:
3727 conn.do_handshake()
3728 except WantReadError:
3729 pass
3730 data = conn.bio_read(2)
3731 self.assertEqual(2, len(data))
3732
3733
3734 if not PY3:
3735 def test_buffer_size_long(self):
3736 """
3737 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3738 :py:obj:`long` as well as :py:obj:`int`.
3739 """
3740 ctx = Context(TLSv1_METHOD)
3741 conn = Connection(ctx, None)
3742 conn.set_connect_state()
3743 try:
3744 conn.do_handshake()
3745 except WantReadError:
3746 pass
3747 data = conn.bio_read(long(2))
3748 self.assertEqual(2, len(data))
3749
3750
3751
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003752
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003753class InfoConstantTests(TestCase):
3754 """
3755 Tests for assorted constants exposed for use in info callbacks.
3756 """
3757 def test_integers(self):
3758 """
3759 All of the info constants are integers.
3760
3761 This is a very weak test. It would be nice to have one that actually
3762 verifies that as certain info events happen, the value passed to the
3763 info callback matches up with the constant exposed by OpenSSL.SSL.
3764 """
3765 for const in [
3766 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3767 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3768 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3769 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3770 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
3771 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
3772
3773 self.assertTrue(isinstance(const, int))
3774
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003775
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003776if __name__ == '__main__':
3777 main()