blob: d846aed43e8d0d20645c31dafb9a8247ee44ad01 [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 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002464 If called with an object that is not an instance of
2465 :py:class:`Session`, or with other than one argument,
2466 :py:obj:`Connection.set_session` raises :py:obj:`TypeError`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002467 """
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 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002627 The TLS Finished message send by server must be the TLS Finished
2628 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002629
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002630 The TLS Finished message send by client must be the TLS Finished
2631 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002632 """
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 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002744 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if
2745 called with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002746 """
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
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002750 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002751 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002752 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2753 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002754 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002755 connection = Connection(Context(TLSv1_METHOD), None)
2756 ciphers = connection.get_cipher_list()
2757 self.assertTrue(isinstance(ciphers, list))
2758 for cipher in ciphers:
2759 self.assertTrue(isinstance(cipher, str))
2760
2761
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002762class ConnectionSendTests(TestCase, _LoopbackMixin):
2763 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002764 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002765 """
2766 def test_wrong_args(self):
2767 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002768 When called with arguments other than string argument for its first
2769 parameter or more than two arguments, :py:obj:`Connection.send` raises
2770 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002771 """
2772 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002773 self.assertRaises(TypeError, connection.send)
2774 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002775 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002776
2777
2778 def test_short_bytes(self):
2779 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002780 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002781 and returns the number of bytes sent.
2782 """
2783 server, client = self._loopback()
2784 count = server.send(b('xy'))
2785 self.assertEquals(count, 2)
2786 self.assertEquals(client.recv(2), b('xy'))
2787
Abraham Martinef063482015-03-25 14:06:24 +00002788
2789 def test_text(self):
2790 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002791 When passed a text, :py:obj:`Connection.send` transmits all of it and
2792 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002793 """
2794 server, client = self._loopback()
2795 with catch_warnings(record=True) as w:
2796 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002797 count = server.send(b"xy".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002798 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002799 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002800 WARNING_TYPE_EXPECTED
2801 ),
2802 str(w[-1].message)
2803 )
2804 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinef063482015-03-25 14:06:24 +00002805 self.assertEquals(count, 2)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002806 self.assertEquals(client.recv(2), b"xy")
Abraham Martinef063482015-03-25 14:06:24 +00002807
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002808 try:
2809 memoryview
2810 except NameError:
2811 "cannot test sending memoryview without memoryview"
2812 else:
2813 def test_short_memoryview(self):
2814 """
2815 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002816 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002817 bytes sent.
2818 """
2819 server, client = self._loopback()
2820 count = server.send(memoryview(b('xy')))
2821 self.assertEquals(count, 2)
2822 self.assertEquals(client.recv(2), b('xy'))
2823
2824
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002825 try:
2826 buffer
2827 except NameError:
2828 "cannot test sending buffer without buffer"
2829 else:
2830 def test_short_buffer(self):
2831 """
2832 When passed a buffer containing a small number of bytes,
2833 :py:obj:`Connection.send` transmits all of them and returns the number of
2834 bytes sent.
2835 """
2836 server, client = self._loopback()
2837 count = server.send(buffer(b('xy')))
2838 self.assertEquals(count, 2)
2839 self.assertEquals(client.recv(2), b('xy'))
2840
2841
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002842
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002843def _make_memoryview(size):
2844 """
2845 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2846 size.
2847 """
2848 return memoryview(bytearray(size))
2849
2850
2851
Cory Benfield62d10332014-06-15 10:03:41 +01002852class ConnectionRecvIntoTests(TestCase, _LoopbackMixin):
2853 """
2854 Tests for :py:obj:`Connection.recv_into`
2855 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002856 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002857 """
2858 Assert that when the given buffer is passed to
2859 ``Connection.recv_into``, whatever bytes are available to be received
2860 that fit into that buffer are written into that buffer.
2861 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002862 output_buffer = factory(5)
2863
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002864 server, client = self._loopback()
2865 server.send(b('xy'))
2866
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002867 self.assertEqual(client.recv_into(output_buffer), 2)
2868 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002869
2870
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002871 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002872 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002873 :py:obj:`Connection.recv_into` can be passed a ``bytearray`` instance
2874 and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002875 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002876 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002877
2878
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002879 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002880 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002881 Assert that when the given buffer is passed to ``Connection.recv_into``
2882 along with a value for ``nbytes`` that is less than the size of that
2883 buffer, only ``nbytes`` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002884 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002885 output_buffer = factory(10)
2886
Cory Benfield62d10332014-06-15 10:03:41 +01002887 server, client = self._loopback()
2888 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002889
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002890 self.assertEqual(client.recv_into(output_buffer, 5), 5)
2891 self.assertEqual(
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002892 output_buffer, bytearray(b('abcde\x00\x00\x00\x00\x00'))
2893 )
2894
2895
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002896 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002897 """
2898 When called with a ``bytearray`` instance,
2899 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter and
2900 doesn't copy in more than that number of bytes.
2901 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002902 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002903
2904
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002905 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002906 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002907 Assert that if there are more bytes available to be read from the
2908 receive buffer than would fit into the buffer passed to
2909 :py:obj:`Connection.recv_into`, only as many as fit are written into
2910 it.
Cory Benfield62d10332014-06-15 10:03:41 +01002911 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002912 output_buffer = factory(5)
2913
Cory Benfield62d10332014-06-15 10:03:41 +01002914 server, client = self._loopback()
2915 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002916
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002917 self.assertEqual(client.recv_into(output_buffer), 5)
2918 self.assertEqual(output_buffer, bytearray(b('abcde')))
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002919 rest = client.recv(5)
2920 self.assertEqual(b('fghij'), rest)
2921
2922
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002923 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002924 """
2925 When called with a ``bytearray`` instance,
2926 :py:obj:`Connection.recv_into` respects the size of the array and
2927 doesn't write more bytes into it than will fit.
2928 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002929 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002930
2931
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002932 def _really_doesnt_overfill_test(self, factory):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002933 """
2934 Assert that if the value given by ``nbytes`` is greater than the actual
2935 size of the output buffer passed to :py:obj:`Connection.recv_into`, the
2936 behavior is as if no value was given for ``nbytes`` at all.
2937 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002938 output_buffer = factory(5)
2939
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002940 server, client = self._loopback()
2941 server.send(b('abcdefghij'))
2942
2943 self.assertEqual(client.recv_into(output_buffer, 50), 5)
2944 self.assertEqual(output_buffer, bytearray(b('abcde')))
2945 rest = client.recv(5)
2946 self.assertEqual(b('fghij'), rest)
2947
2948
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002949 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002950 """
2951 When called with a ``bytearray`` instance and an ``nbytes`` value that
2952 is too large, :py:obj:`Connection.recv_into` respects the size of the
2953 array and not the ``nbytes`` value and doesn't write more bytes into
2954 the buffer than will fit.
2955 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002956 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002957
2958
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002959 def test_peek(self):
2960
2961 server, client = self._loopback()
2962 server.send(b('xy'))
2963
2964 for _ in range(2):
2965 output_buffer = bytearray(5)
2966 self.assertEqual(client.recv_into(output_buffer, flags=MSG_PEEK), 2)
2967 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
2968
2969
Cory Benfield62d10332014-06-15 10:03:41 +01002970 try:
2971 memoryview
2972 except NameError:
2973 "cannot test recv_into memoryview without memoryview"
2974 else:
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002975 def test_memoryview_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002976 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002977 :py:obj:`Connection.recv_into` can be passed a ``memoryview``
2978 instance and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002979 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002980 self._no_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002981
2982
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002983 def test_memoryview_respects_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002984 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002985 When called with a ``memoryview`` instance,
2986 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter
2987 and doesn't copy more than that number of bytes in.
Cory Benfield62d10332014-06-15 10:03:41 +01002988 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002989 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002990
2991
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002992 def test_memoryview_doesnt_overfill(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002993 """
Jean-Paul Calderone8fd82552015-03-15 17:21:07 -04002994 When called with a ``memoryview`` instance,
2995 :py:obj:`Connection.recv_into` respects the size of the array and
2996 doesn't write more bytes into it than will fit.
Cory Benfield62d10332014-06-15 10:03:41 +01002997 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002998 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002999
3000
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003001 def test_memoryview_really_doesnt_overfill(self):
3002 """
3003 When called with a ``memoryview`` instance and an ``nbytes`` value
3004 that is too large, :py:obj:`Connection.recv_into` respects the size
3005 of the array and not the ``nbytes`` value and doesn't write more
3006 bytes into the buffer than will fit.
3007 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003008 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003009
3010
Cory Benfield62d10332014-06-15 10:03:41 +01003011
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003012class ConnectionSendallTests(TestCase, _LoopbackMixin):
3013 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003014 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003015 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003016 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003017 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003018 When called with arguments other than a string argument for its first
3019 parameter or with more than two arguments, :py:obj:`Connection.sendall`
3020 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003021 """
3022 connection = Connection(Context(TLSv1_METHOD), None)
3023 self.assertRaises(TypeError, connection.sendall)
3024 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003025 self.assertRaises(
3026 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003027
3028
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003029 def test_short(self):
3030 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003031 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003032 it.
3033 """
3034 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04003035 server.sendall(b('x'))
3036 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003037
3038
Abraham Martinef063482015-03-25 14:06:24 +00003039 def test_text(self):
3040 """
Jean-Paul Calderone93477422015-04-13 20:38:57 -04003041 :py:obj:`Connection.sendall` transmits all the content in the string
3042 passed to it raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003043 """
3044 server, client = self._loopback()
3045 with catch_warnings(record=True) as w:
3046 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003047 server.sendall(b"x".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003048 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003049 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003050 WARNING_TYPE_EXPECTED
3051 ),
3052 str(w[-1].message)
3053 )
3054 self.assertIs(w[-1].category, DeprecationWarning)
3055 self.assertEquals(client.recv(1), b"x")
Abraham Martinef063482015-03-25 14:06:24 +00003056
3057
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003058 try:
3059 memoryview
3060 except NameError:
3061 "cannot test sending memoryview without memoryview"
3062 else:
3063 def test_short_memoryview(self):
3064 """
3065 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003066 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003067 """
3068 server, client = self._loopback()
3069 server.sendall(memoryview(b('x')))
3070 self.assertEquals(client.recv(1), b('x'))
3071
3072
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003073 try:
3074 buffer
3075 except NameError:
3076 "cannot test sending buffers without buffers"
3077 else:
3078 def test_short_buffers(self):
3079 """
3080 When passed a buffer containing a small number of bytes,
3081 :py:obj:`Connection.sendall` transmits all of them.
3082 """
3083 server, client = self._loopback()
3084 server.sendall(buffer(b('x')))
3085 self.assertEquals(client.recv(1), b('x'))
3086
3087
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003088 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003089 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003090 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003091 it even if this requires multiple calls of an underlying write function.
3092 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003093 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003094 # Should be enough, underlying SSL_write should only do 16k at a time.
3095 # On Windows, after 32k of bytes the write will block (forever - because
3096 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04003097 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003098 server.sendall(message)
3099 accum = []
3100 received = 0
3101 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003102 data = client.recv(1024)
3103 accum.append(data)
3104 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04003105 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003106
3107
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003108 def test_closed(self):
3109 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003110 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003111 write error from the low level write call.
3112 """
3113 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003114 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003115 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003116 if platform == "win32":
3117 self.assertEqual(exc.args[0], ESHUTDOWN)
3118 else:
3119 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003120
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003121
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04003122
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003123class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
3124 """
3125 Tests for SSL renegotiation APIs.
3126 """
3127 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003128 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003129 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003130 arguments.
3131 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003132 connection = Connection(Context(TLSv1_METHOD), None)
3133 self.assertRaises(TypeError, connection.renegotiate, None)
3134
3135
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003136 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003137 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003138 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003139 any arguments.
3140 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003141 connection = Connection(Context(TLSv1_METHOD), None)
3142 self.assertRaises(TypeError, connection.total_renegotiations, None)
3143
3144
3145 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003146 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003147 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003148 renegotiations have happened.
3149 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003150 connection = Connection(Context(TLSv1_METHOD), None)
3151 self.assertEquals(connection.total_renegotiations(), 0)
3152
3153
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003154# def test_renegotiate(self):
3155# """
3156# """
3157# server, client = self._loopback()
3158
3159# server.send("hello world")
3160# self.assertEquals(client.recv(len("hello world")), "hello world")
3161
3162# self.assertEquals(server.total_renegotiations(), 0)
3163# self.assertTrue(server.renegotiate())
3164
3165# server.setblocking(False)
3166# client.setblocking(False)
3167# while server.renegotiate_pending():
3168# client.do_handshake()
3169# server.do_handshake()
3170
3171# self.assertEquals(server.total_renegotiations(), 1)
3172
3173
3174
3175
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003176class ErrorTests(TestCase):
3177 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003178 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003179 """
3180 def test_type(self):
3181 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003182 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003183 """
3184 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05003185 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05003186
3187
3188
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003189class ConstantsTests(TestCase):
3190 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003191 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003192
3193 These are values defined by OpenSSL intended only to be used as flags to
3194 OpenSSL APIs. The only assertions it seems can be made about them is
3195 their values.
3196 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003197 # unittest.TestCase has no skip mechanism
3198 if OP_NO_QUERY_MTU is not None:
3199 def test_op_no_query_mtu(self):
3200 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003201 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003202 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003203 """
3204 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
3205 else:
3206 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003207
3208
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003209 if OP_COOKIE_EXCHANGE is not None:
3210 def test_op_cookie_exchange(self):
3211 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003212 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003213 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003214 """
3215 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
3216 else:
3217 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003218
3219
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003220 if OP_NO_TICKET is not None:
3221 def test_op_no_ticket(self):
3222 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003223 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003224 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003225 """
3226 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04003227 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003228 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05003229
3230
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003231 if OP_NO_COMPRESSION is not None:
3232 def test_op_no_compression(self):
3233 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003234 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
3235 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003236 """
3237 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
3238 else:
3239 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3240
3241
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003242 def test_sess_cache_off(self):
3243 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003244 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3245 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003246 """
3247 self.assertEqual(0x0, SESS_CACHE_OFF)
3248
3249
3250 def test_sess_cache_client(self):
3251 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003252 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3253 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003254 """
3255 self.assertEqual(0x1, SESS_CACHE_CLIENT)
3256
3257
3258 def test_sess_cache_server(self):
3259 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003260 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3261 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003262 """
3263 self.assertEqual(0x2, SESS_CACHE_SERVER)
3264
3265
3266 def test_sess_cache_both(self):
3267 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003268 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3269 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003270 """
3271 self.assertEqual(0x3, SESS_CACHE_BOTH)
3272
3273
3274 def test_sess_cache_no_auto_clear(self):
3275 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003276 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3277 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3278 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003279 """
3280 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
3281
3282
3283 def test_sess_cache_no_internal_lookup(self):
3284 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003285 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3286 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3287 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003288 """
3289 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
3290
3291
3292 def test_sess_cache_no_internal_store(self):
3293 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003294 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3295 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3296 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003297 """
3298 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
3299
3300
3301 def test_sess_cache_no_internal(self):
3302 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003303 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3304 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
3305 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003306 """
3307 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
3308
3309
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04003310
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003311class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05003312 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003313 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003314 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003315 def _server(self, sock):
3316 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003317 Create a new server-side SSL :py:obj:`Connection` object wrapped around
3318 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003319 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003320 # Create the server side Connection. This is mostly setup boilerplate
3321 # - use TLSv1, use a particular certificate, etc.
3322 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003323 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
3324 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 -04003325 server_store = server_ctx.get_cert_store()
3326 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3327 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3328 server_ctx.check_privatekey()
3329 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003330 # Here the Connection is actually created. If None is passed as the 2nd
3331 # parameter, it indicates a memory BIO should be created.
3332 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003333 server_conn.set_accept_state()
3334 return server_conn
3335
3336
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003337 def _client(self, sock):
3338 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003339 Create a new client-side SSL :py:obj:`Connection` object wrapped around
3340 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003341 """
3342 # Now create the client side Connection. Similar boilerplate to the
3343 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003344 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003345 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
3346 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 -04003347 client_store = client_ctx.get_cert_store()
3348 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
3349 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
3350 client_ctx.check_privatekey()
3351 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003352 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003353 client_conn.set_connect_state()
3354 return client_conn
3355
3356
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003357 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003358 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003359 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003360 reading from the output of each and writing those bytes to the input of
3361 the other and in this way establish a connection and exchange
3362 application-level bytes with each other.
3363 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003364 server_conn = self._server(None)
3365 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003366
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003367 # There should be no key or nonces yet.
3368 self.assertIdentical(server_conn.master_key(), None)
3369 self.assertIdentical(server_conn.client_random(), None)
3370 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003371
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003372 # First, the handshake needs to happen. We'll deliver bytes back and
3373 # forth between the client and server until neither of them feels like
3374 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003375 self.assertIdentical(
3376 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003377
3378 # Now that the handshake is done, there should be a key and nonces.
3379 self.assertNotIdentical(server_conn.master_key(), None)
3380 self.assertNotIdentical(server_conn.client_random(), None)
3381 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04003382 self.assertEquals(server_conn.client_random(), client_conn.client_random())
3383 self.assertEquals(server_conn.server_random(), client_conn.server_random())
3384 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
3385 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003386
3387 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003388 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05003389
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003390 server_conn.write(important_message)
3391 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003392 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003393 (client_conn, important_message))
3394
3395 client_conn.write(important_message[::-1])
3396 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003397 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003398 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003399
3400
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003401 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003402 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003403 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003404
3405 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09003406 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003407 this test fails, there must be a problem outside the memory BIO
3408 code, as no memory BIO is involved here). Even though this isn't a
3409 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003410 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04003411 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003412
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003413 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05003414 client_conn.send(important_message)
3415 msg = server_conn.recv(1024)
3416 self.assertEqual(msg, important_message)
3417
3418 # Again in the other direction, just for fun.
3419 important_message = important_message[::-1]
3420 server_conn.send(important_message)
3421 msg = client_conn.recv(1024)
3422 self.assertEqual(msg, important_message)
3423
3424
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04003425 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003426 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003427 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
3428 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003429 """
3430 context = Context(SSLv3_METHOD)
3431 client = socket()
3432 clientSSL = Connection(context, client)
Alex Gaynor43307782015-09-04 09:05:45 -04003433 self.assertRaises(TypeError, clientSSL.bio_read, 100)
3434 self.assertRaises(TypeError, clientSSL.bio_write, "foo")
Alex Gaynor7e8b61e2015-09-04 13:13:05 -04003435 self.assertRaises(TypeError, clientSSL.bio_shutdown)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003436
3437
3438 def test_outgoingOverflow(self):
3439 """
3440 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09003441 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003442 returned and that many bytes from the beginning of the input can be
3443 read from the other end of the connection.
3444 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003445 server = self._server(None)
3446 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003447
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003448 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003449
3450 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003451 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003452 # Sanity check. We're trying to test what happens when the entire
3453 # input can't be sent. If the entire input was sent, this test is
3454 # meaningless.
3455 self.assertTrue(sent < size)
3456
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003457 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003458 self.assertIdentical(receiver, server)
3459
3460 # We can rely on all of these bytes being received at once because
3461 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
3462 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003463
3464
3465 def test_shutdown(self):
3466 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003467 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
3468 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003469 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003470 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003471 server.bio_shutdown()
3472 e = self.assertRaises(Error, server.recv, 1024)
3473 # We don't want WantReadError or ZeroReturnError or anything - it's a
3474 # handshake failure.
3475 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003476
3477
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003478 def test_unexpectedEndOfFile(self):
3479 """
3480 If the connection is lost before an orderly SSL shutdown occurs,
3481 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
3482 "Unexpected EOF".
3483 """
3484 server_conn, client_conn = self._loopback()
3485 client_conn.sock_shutdown(SHUT_RDWR)
3486 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
3487 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
3488
3489
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003490 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003491 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003492 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 -04003493
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003494 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003495 before the client and server are connected to each other. This
3496 function should specify a list of CAs for the server to send to the
3497 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09003498 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003499 times.
3500 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003501 server = self._server(None)
3502 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003503 self.assertEqual(client.get_client_ca_list(), [])
3504 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003505 ctx = server.get_context()
3506 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003507 self.assertEqual(client.get_client_ca_list(), [])
3508 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003509 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003510 self.assertEqual(client.get_client_ca_list(), expected)
3511 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003512
3513
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003514 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003515 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003516 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003517 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003518 """
3519 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003520 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
3521 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
3522 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003523
3524
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003525 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003526 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003527 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003528 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09003529 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003530 after the connection is set up.
3531 """
3532 def no_ca(ctx):
3533 ctx.set_client_ca_list([])
3534 return []
3535 self._check_client_ca_list(no_ca)
3536
3537
3538 def test_set_one_ca_list(self):
3539 """
3540 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003541 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003542 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003543 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003544 X509Name after the connection is set up.
3545 """
3546 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3547 cadesc = cacert.get_subject()
3548 def single_ca(ctx):
3549 ctx.set_client_ca_list([cadesc])
3550 return [cadesc]
3551 self._check_client_ca_list(single_ca)
3552
3553
3554 def test_set_multiple_ca_list(self):
3555 """
3556 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003557 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003558 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003559 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003560 X509Names after the connection is set up.
3561 """
3562 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3563 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3564
3565 sedesc = secert.get_subject()
3566 cldesc = clcert.get_subject()
3567
3568 def multiple_ca(ctx):
3569 L = [sedesc, cldesc]
3570 ctx.set_client_ca_list(L)
3571 return L
3572 self._check_client_ca_list(multiple_ca)
3573
3574
3575 def test_reset_ca_list(self):
3576 """
3577 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09003578 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003579 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003580 """
3581 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3582 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3583 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3584
3585 cadesc = cacert.get_subject()
3586 sedesc = secert.get_subject()
3587 cldesc = clcert.get_subject()
3588
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003589 def changed_ca(ctx):
3590 ctx.set_client_ca_list([sedesc, cldesc])
3591 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003592 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003593 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003594
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003595
3596 def test_mutated_ca_list(self):
3597 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003598 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003599 afterwards, this does not affect the list of CA names sent to the
3600 client.
3601 """
3602 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3603 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3604
3605 cadesc = cacert.get_subject()
3606 sedesc = secert.get_subject()
3607
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003608 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003609 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003610 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003611 L.append(sedesc)
3612 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003613 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003614
3615
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003616 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003617 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003618 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003619 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003620 """
3621 ctx = Context(TLSv1_METHOD)
3622 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003623 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003624 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003625 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003626
3627
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003628 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003629 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003630 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09003631 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003632 """
3633 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3634 cadesc = cacert.get_subject()
3635 def single_ca(ctx):
3636 ctx.add_client_ca(cacert)
3637 return [cadesc]
3638 self._check_client_ca_list(single_ca)
3639
3640
3641 def test_multiple_add_client_ca(self):
3642 """
3643 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09003644 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003645 """
3646 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3647 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3648
3649 cadesc = cacert.get_subject()
3650 sedesc = secert.get_subject()
3651
3652 def multiple_ca(ctx):
3653 ctx.add_client_ca(cacert)
3654 ctx.add_client_ca(secert)
3655 return [cadesc, sedesc]
3656 self._check_client_ca_list(multiple_ca)
3657
3658
3659 def test_set_and_add_client_ca(self):
3660 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003661 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
3662 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003663 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003664 """
3665 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3666 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3667 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3668
3669 cadesc = cacert.get_subject()
3670 sedesc = secert.get_subject()
3671 cldesc = clcert.get_subject()
3672
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003673 def mixed_set_add_ca(ctx):
3674 ctx.set_client_ca_list([cadesc, sedesc])
3675 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003676 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003677 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003678
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003679
3680 def test_set_after_add_client_ca(self):
3681 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003682 A call to :py:obj:`Context.set_client_ca_list` after a call to
3683 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003684 call with the names specified by the latter cal.
3685 """
3686 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3687 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3688 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3689
3690 cadesc = cacert.get_subject()
3691 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003692
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003693 def set_replaces_add_ca(ctx):
3694 ctx.add_client_ca(clcert)
3695 ctx.set_client_ca_list([cadesc])
3696 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003697 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003698 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003699
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003700
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003701
3702class ConnectionBIOTests(TestCase):
3703 """
3704 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3705 """
3706 def test_wantReadError(self):
3707 """
3708 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
3709 if there are no bytes available to be read from the BIO.
3710 """
3711 ctx = Context(TLSv1_METHOD)
3712 conn = Connection(ctx, None)
3713 self.assertRaises(WantReadError, conn.bio_read, 1024)
3714
3715
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003716 def test_buffer_size(self):
3717 """
3718 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3719 number of bytes to read and return.
3720 """
3721 ctx = Context(TLSv1_METHOD)
3722 conn = Connection(ctx, None)
3723 conn.set_connect_state()
3724 try:
3725 conn.do_handshake()
3726 except WantReadError:
3727 pass
3728 data = conn.bio_read(2)
3729 self.assertEqual(2, len(data))
3730
3731
3732 if not PY3:
3733 def test_buffer_size_long(self):
3734 """
3735 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3736 :py:obj:`long` as well as :py:obj:`int`.
3737 """
3738 ctx = Context(TLSv1_METHOD)
3739 conn = Connection(ctx, None)
3740 conn.set_connect_state()
3741 try:
3742 conn.do_handshake()
3743 except WantReadError:
3744 pass
3745 data = conn.bio_read(long(2))
3746 self.assertEqual(2, len(data))
3747
3748
3749
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003750
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003751class InfoConstantTests(TestCase):
3752 """
3753 Tests for assorted constants exposed for use in info callbacks.
3754 """
3755 def test_integers(self):
3756 """
3757 All of the info constants are integers.
3758
3759 This is a very weak test. It would be nice to have one that actually
3760 verifies that as certain info events happen, the value passed to the
3761 info callback matches up with the constant exposed by OpenSSL.SSL.
3762 """
3763 for const in [
3764 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3765 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3766 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3767 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3768 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
3769 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
3770
3771 self.assertTrue(isinstance(const, int))
3772
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003773
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003774if __name__ == '__main__':
3775 main()