blob: bbdd7ec3ec5ea7c36ae8eeb6cd1f3add2f38ce1f [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
Hynek Schlawackf8979a52015-09-05 21:25:25 +020010from sys import platform, getfilesystemencoding, version_info
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 Schlawackf8979a52015-09-05 21:25:25 +0200103skip_if_py26 = pytest.mark.skipif(
104 version_info[0:2] == (2, 6),
105 reason="Python 2.7 and later only"
106)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200107
108
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400109def join_bytes_or_unicode(prefix, suffix):
110 """
111 Join two path components of either ``bytes`` or ``unicode``.
112
113 The return type is the same as the type of ``prefix``.
114 """
115 # If the types are the same, nothing special is necessary.
116 if type(prefix) == type(suffix):
117 return join(prefix, suffix)
118
119 # Otherwise, coerce suffix to the type of prefix.
120 if isinstance(prefix, text_type):
121 return join(prefix, suffix.decode(getfilesystemencoding()))
122 else:
123 return join(prefix, suffix.encode(getfilesystemencoding()))
124
125
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400126def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400127 return ok
128
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400129
Rick Deanb1ccd562009-07-09 23:52:39 -0500130def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400131 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400132 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400133 """
134 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500135 port = socket()
136 port.bind(('', 0))
137 port.listen(1)
138 client = socket()
139 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400140 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400141 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500142 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500143
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400144 # Let's pass some unencrypted data to make sure our socket connection is
145 # fine. Just one byte, so we don't have to worry about buffers getting
146 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400147 server.send(b("x"))
148 assert client.recv(1024) == b("x")
149 client.send(b("y"))
150 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500151
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400152 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400153 server.setblocking(False)
154 client.setblocking(False)
Jim Shaver46f28912015-05-29 19:32:16 -0400155
Rick Deanb1ccd562009-07-09 23:52:39 -0500156 return (server, client)
157
158
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400159def handshake(client, server):
160 conns = [client, server]
161 while conns:
162 for conn in conns:
163 try:
164 conn.do_handshake()
165 except WantReadError:
166 pass
167 else:
168 conns.remove(conn)
169
170
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400171def _create_certificate_chain():
172 """
173 Construct and return a chain of certificates.
174
175 1. A new self-signed certificate authority certificate (cacert)
176 2. A new intermediate certificate signed by cacert (icert)
177 3. A new server certificate signed by icert (scert)
178 """
179 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
180
181 # Step 1
182 cakey = PKey()
183 cakey.generate_key(TYPE_RSA, 512)
184 cacert = X509()
185 cacert.get_subject().commonName = "Authority Certificate"
186 cacert.set_issuer(cacert.get_subject())
187 cacert.set_pubkey(cakey)
188 cacert.set_notBefore(b("20000101000000Z"))
189 cacert.set_notAfter(b("20200101000000Z"))
190 cacert.add_extensions([caext])
191 cacert.set_serial_number(0)
192 cacert.sign(cakey, "sha1")
193
194 # Step 2
195 ikey = PKey()
196 ikey.generate_key(TYPE_RSA, 512)
197 icert = X509()
198 icert.get_subject().commonName = "Intermediate Certificate"
199 icert.set_issuer(cacert.get_subject())
200 icert.set_pubkey(ikey)
201 icert.set_notBefore(b("20000101000000Z"))
202 icert.set_notAfter(b("20200101000000Z"))
203 icert.add_extensions([caext])
204 icert.set_serial_number(0)
205 icert.sign(cakey, "sha1")
206
207 # Step 3
208 skey = PKey()
209 skey.generate_key(TYPE_RSA, 512)
210 scert = X509()
211 scert.get_subject().commonName = "Server Certificate"
212 scert.set_issuer(icert.get_subject())
213 scert.set_pubkey(skey)
214 scert.set_notBefore(b("20000101000000Z"))
215 scert.set_notAfter(b("20200101000000Z"))
216 scert.add_extensions([
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200217 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400218 scert.set_serial_number(0)
219 scert.sign(ikey, "sha1")
220
221 return [(cakey, cacert), (ikey, icert), (skey, scert)]
222
223
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400224class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400225 """
226 Helper mixin which defines methods for creating a connected socket pair and
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200227 for forcing two connected SSL sockets to talk to each other via memory
228 BIOs.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400229 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500230 def _loopbackClientFactory(self, socket):
231 client = Connection(Context(TLSv1_METHOD), socket)
232 client.set_connect_state()
233 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400234
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500235 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400236 ctx = Context(TLSv1_METHOD)
237 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
238 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500239 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400240 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500241 return server
242
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500243 def _loopback(self, serverFactory=None, clientFactory=None):
244 if serverFactory is None:
245 serverFactory = self._loopbackServerFactory
246 if clientFactory is None:
247 clientFactory = self._loopbackClientFactory
248
249 (server, client) = socket_pair()
250 server = serverFactory(server)
251 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400252
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400253 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400254
255 server.setblocking(True)
256 client.setblocking(True)
257 return server, client
258
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400259 def _interactInMemory(self, client_conn, server_conn):
260 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900261 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400262 objects. Copy bytes back and forth between their send/receive buffers
263 for as long as there is anything to copy. When there is nothing more
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200264 to copy, return :py:obj:`None`. If one of them actually manages to
265 deliver some application bytes, return a two-tuple of the connection
266 from which the bytes were read and the bytes themselves.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400267 """
268 wrote = True
269 while wrote:
270 # Loop until neither side has anything to say
271 wrote = False
272
273 # Copy stuff from each side's send buffer to the other side's
274 # receive buffer.
275 for (read, write) in [(client_conn, server_conn),
276 (server_conn, client_conn)]:
277
278 # Give the side a chance to generate some more bytes, or
279 # succeed.
280 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400281 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400282 except WantReadError:
283 # It didn't succeed, so we'll hope it generated some
284 # output.
285 pass
286 else:
287 # It did succeed, so we'll stop now and let the caller deal
288 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400289 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400290
291 while True:
292 # Keep copying as long as there's more stuff there.
293 try:
294 dirty = read.bio_read(4096)
295 except WantReadError:
296 # Okay, nothing more waiting to be sent. Stop
297 # processing this send buffer.
298 break
299 else:
300 # Keep track of the fact that someone generated some
301 # output.
302 wrote = True
303 write.bio_write(dirty)
304
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400305 def _handshakeInMemory(self, client_conn, server_conn):
Jean-Paul Calderoneb2b40782014-05-06 08:47:40 -0400306 """
307 Perform the TLS handshake between two :py:class:`Connection` instances
308 connected to each other via memory BIOs.
309 """
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400310 client_conn.set_connect_state()
311 server_conn.set_accept_state()
312
313 for conn in [client_conn, server_conn]:
314 try:
315 conn.do_handshake()
316 except WantReadError:
317 pass
318
319 self._interactInMemory(client_conn, server_conn)
320
321
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400322class VersionTests(TestCase):
323 """
324 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900325 :py:obj:`OpenSSL.SSL.SSLeay_version` and
326 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400327 """
328 def test_OPENSSL_VERSION_NUMBER(self):
329 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900330 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400331 byte and the patch, fix, minor, and major versions in the
332 nibbles above that.
333 """
334 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
335
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400336 def test_SSLeay_version(self):
337 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900338 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400339 one of a number of version strings based on that indicator.
340 """
341 versions = {}
342 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
343 SSLEAY_PLATFORM, SSLEAY_DIR]:
344 version = SSLeay_version(t)
345 versions[version] = t
346 self.assertTrue(isinstance(version, bytes))
347 self.assertEqual(len(versions), 5)
348
349
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400350class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400351 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900352 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400353 """
354 def test_method(self):
355 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200356 :py:obj:`Context` can be instantiated with one of
357 :py:obj:`SSLv2_METHOD`, :py:obj:`SSLv3_METHOD`,
358 :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400359 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400360 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400361 methods = [
362 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
363 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400364 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400365
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400366 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
367 for meth in maybe:
368 try:
369 Context(meth)
370 except (Error, ValueError):
371 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
372 # don't. Difficult to say in advance.
373 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400374
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400375 self.assertRaises(TypeError, Context, "")
376 self.assertRaises(ValueError, Context, 10)
377
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200378 @skip_if_py3
379 def test_method_long(self):
380 """
381 On Python 2 :py:class:`Context` accepts values of type
382 :py:obj:`long` as well as :py:obj:`int`.
383 """
384 Context(long(TLSv1_METHOD))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500385
Rick Deane15b1472009-07-09 15:53:42 -0500386 def test_type(self):
387 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200388 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type
389 object and can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500390 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400391 self.assertIdentical(Context, ContextType)
392 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500393
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400394 def test_use_privatekey(self):
395 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200396 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey`
397 instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400398 """
399 key = PKey()
400 key.generate_key(TYPE_RSA, 128)
401 ctx = Context(TLSv1_METHOD)
402 ctx.use_privatekey(key)
403 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400404
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800405 def test_use_privatekey_file_missing(self):
406 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200407 :py:obj:`Context.use_privatekey_file` raises
408 :py:obj:`OpenSSL.SSL.Error` when passed the name of a file which does
409 not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800410 """
411 ctx = Context(TLSv1_METHOD)
412 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
413
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400414 def _use_privatekey_file_test(self, pemfile, filetype):
415 """
416 Verify that calling ``Context.use_privatekey_file`` with the given
417 arguments does not raise an exception.
418 """
419 key = PKey()
420 key.generate_key(TYPE_RSA, 128)
421
422 with open(pemfile, "wt") as pem:
423 pem.write(
424 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
425 )
426
427 ctx = Context(TLSv1_METHOD)
428 ctx.use_privatekey_file(pemfile, filetype)
429
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400430 def test_use_privatekey_file_bytes(self):
431 """
432 A private key can be specified from a file by passing a ``bytes``
433 instance giving the file name to ``Context.use_privatekey_file``.
434 """
435 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400436 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400437 FILETYPE_PEM,
438 )
439
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400440 def test_use_privatekey_file_unicode(self):
441 """
442 A private key can be specified from a file by passing a ``unicode``
443 instance giving the file name to ``Context.use_privatekey_file``.
444 """
445 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400446 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400447 FILETYPE_PEM,
448 )
449
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200450 @skip_if_py3
451 def test_use_privatekey_file_long(self):
452 """
453 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
454 filetype of type :py:obj:`long` as well as :py:obj:`int`.
455 """
456 self._use_privatekey_file_test(self.mktemp(), long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500457
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800458 def test_use_certificate_wrong_args(self):
459 """
460 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200461 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as
462 an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800463 """
464 ctx = Context(TLSv1_METHOD)
465 self.assertRaises(TypeError, ctx.use_certificate)
466 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200467 self.assertRaises(
468 TypeError, ctx.use_certificate, X509(), "hello, world"
469 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800470
471 def test_use_certificate_uninitialized(self):
472 """
473 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
474 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
475 initialized (ie, which does not actually have any certificate data).
476 """
477 ctx = Context(TLSv1_METHOD)
478 self.assertRaises(Error, ctx.use_certificate, X509())
479
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800480 def test_use_certificate(self):
481 """
482 :py:obj:`Context.use_certificate` sets the certificate which will be
483 used to identify connections created using the context.
484 """
485 # TODO
486 # Hard to assert anything. But we could set a privatekey then ask
487 # OpenSSL if the cert and key agree using check_privatekey. Then as
488 # long as check_privatekey works right we're good...
489 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200490 ctx.use_certificate(
491 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
492 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800493
494 def test_use_certificate_file_wrong_args(self):
495 """
496 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
497 called with zero arguments or more than two arguments, or if the first
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200498 argument is not a byte string or the second argumnent is not an
499 integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800500 """
501 ctx = Context(TLSv1_METHOD)
502 self.assertRaises(TypeError, ctx.use_certificate_file)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200503 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile",
504 object())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800505 self.assertRaises(
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200506 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM,
507 object())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800508 self.assertRaises(
509 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
510 self.assertRaises(
511 TypeError, ctx.use_certificate_file, b"somefile", object())
512
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800513 def test_use_certificate_file_missing(self):
514 """
515 :py:obj:`Context.use_certificate_file` raises
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200516 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does
517 not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800518 """
519 ctx = Context(TLSv1_METHOD)
520 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
521
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400522 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800523 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400524 Verify that calling ``Context.use_certificate_file`` with the given
525 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800526 """
527 # TODO
528 # Hard to assert anything. But we could set a privatekey then ask
529 # OpenSSL if the cert and key agree using check_privatekey. Then as
530 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400531 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800532 pem_file.write(cleartextCertificatePEM)
533
534 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400535 ctx.use_certificate_file(certificate_file)
536
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400537 def test_use_certificate_file_bytes(self):
538 """
539 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
540 ``bytes`` filename) which will be used to identify connections created
541 using the context.
542 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400543 filename = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400544 self._use_certificate_file_test(filename)
545
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400546 def test_use_certificate_file_unicode(self):
547 """
548 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
549 ``bytes`` filename) which will be used to identify connections created
550 using the context.
551 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400552 filename = self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400553 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800554
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200555 @skip_if_py3
556 def test_use_certificate_file_long(self):
557 """
558 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
559 filetype of type :py:obj:`long` as well as :py:obj:`int`.
560 """
561 pem_filename = self.mktemp()
562 with open(pem_filename, "wb") as pem_file:
563 pem_file.write(cleartextCertificatePEM)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500564
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200565 ctx = Context(TLSv1_METHOD)
566 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500567
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500568 def test_check_privatekey_valid(self):
569 """
570 :py:obj:`Context.check_privatekey` returns :py:obj:`None` if the
571 :py:obj:`Context` instance has been configured to use a matched key and
572 certificate pair.
573 """
574 key = load_privatekey(FILETYPE_PEM, client_key_pem)
575 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
576 context = Context(TLSv1_METHOD)
577 context.use_privatekey(key)
578 context.use_certificate(cert)
579 self.assertIs(None, context.check_privatekey())
580
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500581 def test_check_privatekey_invalid(self):
582 """
583 :py:obj:`Context.check_privatekey` raises :py:obj:`Error` if the
584 :py:obj:`Context` instance has been configured to use a key and
585 certificate pair which don't relate to each other.
586 """
587 key = load_privatekey(FILETYPE_PEM, client_key_pem)
588 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
589 context = Context(TLSv1_METHOD)
590 context.use_privatekey(key)
591 context.use_certificate(cert)
592 self.assertRaises(Error, context.check_privatekey)
593
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500594 def test_check_privatekey_wrong_args(self):
595 """
596 :py:obj:`Context.check_privatekey` raises :py:obj:`TypeError` if called
597 with other than no arguments.
598 """
599 context = Context(TLSv1_METHOD)
600 self.assertRaises(TypeError, context.check_privatekey, object())
601
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400602 def test_set_app_data_wrong_args(self):
603 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200604 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called
605 with other than one argument.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400606 """
607 context = Context(TLSv1_METHOD)
608 self.assertRaises(TypeError, context.set_app_data)
609 self.assertRaises(TypeError, context.set_app_data, None, None)
610
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400611 def test_get_app_data_wrong_args(self):
612 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200613 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called
614 with any arguments.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400615 """
616 context = Context(TLSv1_METHOD)
617 self.assertRaises(TypeError, context.get_app_data, None)
618
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400619 def test_app_data(self):
620 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200621 :py:obj:`Context.set_app_data` stores an object for later retrieval
622 using :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400623 """
624 app_data = object()
625 context = Context(TLSv1_METHOD)
626 context.set_app_data(app_data)
627 self.assertIdentical(context.get_app_data(), app_data)
628
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400629 def test_set_options_wrong_args(self):
630 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200631 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with
632 the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400633 """
634 context = Context(TLSv1_METHOD)
635 self.assertRaises(TypeError, context.set_options)
636 self.assertRaises(TypeError, context.set_options, None)
637 self.assertRaises(TypeError, context.set_options, 1, None)
638
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500639 def test_set_options(self):
640 """
641 :py:obj:`Context.set_options` returns the new options value.
642 """
643 context = Context(TLSv1_METHOD)
644 options = context.set_options(OP_NO_SSLv2)
645 self.assertTrue(OP_NO_SSLv2 & options)
646
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200647 @skip_if_py3
648 def test_set_options_long(self):
649 """
650 On Python 2 :py:obj:`Context.set_options` accepts values of type
651 :py:obj:`long` as well as :py:obj:`int`.
652 """
653 context = Context(TLSv1_METHOD)
654 options = context.set_options(long(OP_NO_SSLv2))
655 self.assertTrue(OP_NO_SSLv2 & options)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500656
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300657 def test_set_mode_wrong_args(self):
658 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200659 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with
660 the wrong number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300661 """
662 context = Context(TLSv1_METHOD)
663 self.assertRaises(TypeError, context.set_mode)
664 self.assertRaises(TypeError, context.set_mode, None)
665 self.assertRaises(TypeError, context.set_mode, 1, None)
666
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400667 if MODE_RELEASE_BUFFERS is not None:
668 def test_set_mode(self):
669 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200670 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the
671 newly set mode.
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400672 """
673 context = Context(TLSv1_METHOD)
674 self.assertTrue(
675 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500676
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200677 @skip_if_py3
678 def test_set_mode_long(self):
679 """
680 On Python 2 :py:obj:`Context.set_mode` accepts values of type
681 :py:obj:`long` as well as :py:obj:`int`.
682 """
683 context = Context(TLSv1_METHOD)
684 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
685 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400686 else:
687 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
688
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400689 def test_set_timeout_wrong_args(self):
690 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200691 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with
692 the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400693 """
694 context = Context(TLSv1_METHOD)
695 self.assertRaises(TypeError, context.set_timeout)
696 self.assertRaises(TypeError, context.set_timeout, None)
697 self.assertRaises(TypeError, context.set_timeout, 1, None)
698
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400699 def test_get_timeout_wrong_args(self):
700 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200701 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with
702 any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400703 """
704 context = Context(TLSv1_METHOD)
705 self.assertRaises(TypeError, context.get_timeout, None)
706
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400707 def test_timeout(self):
708 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200709 :py:obj:`Context.set_timeout` sets the session timeout for all
710 connections created using the context object.
711 :py:obj:`Context.get_timeout` retrieves this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400712 """
713 context = Context(TLSv1_METHOD)
714 context.set_timeout(1234)
715 self.assertEquals(context.get_timeout(), 1234)
716
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200717 @skip_if_py3
718 def test_timeout_long(self):
719 """
720 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
721 `long` as well as int.
722 """
723 context = Context(TLSv1_METHOD)
724 context.set_timeout(long(1234))
725 self.assertEquals(context.get_timeout(), 1234)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500726
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400727 def test_set_verify_depth_wrong_args(self):
728 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200729 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called
730 with the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400731 """
732 context = Context(TLSv1_METHOD)
733 self.assertRaises(TypeError, context.set_verify_depth)
734 self.assertRaises(TypeError, context.set_verify_depth, None)
735 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
736
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400737 def test_get_verify_depth_wrong_args(self):
738 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200739 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called
740 with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400741 """
742 context = Context(TLSv1_METHOD)
743 self.assertRaises(TypeError, context.get_verify_depth, None)
744
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400745 def test_verify_depth(self):
746 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200747 :py:obj:`Context.set_verify_depth` sets the number of certificates in
748 a chain to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900749 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400750 """
751 context = Context(TLSv1_METHOD)
752 context.set_verify_depth(11)
753 self.assertEquals(context.get_verify_depth(), 11)
754
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200755 @skip_if_py3
756 def test_verify_depth_long(self):
757 """
758 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
759 type `long` as well as int.
760 """
761 context = Context(TLSv1_METHOD)
762 context.set_verify_depth(long(11))
763 self.assertEquals(context.get_verify_depth(), 11)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500764
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400765 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400766 """
767 Write a new private key out to a new file, encrypted using the given
768 passphrase. Return the path to the new file.
769 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400770 key = PKey()
771 key.generate_key(TYPE_RSA, 128)
772 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400773 fObj = open(pemFile, 'w')
774 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
775 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400776 fObj.close()
777 return pemFile
778
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400779 def test_set_passwd_cb_wrong_args(self):
780 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200781 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called
782 with the wrong arguments or with a non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400783 """
784 context = Context(TLSv1_METHOD)
785 self.assertRaises(TypeError, context.set_passwd_cb)
786 self.assertRaises(TypeError, context.set_passwd_cb, None)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200787 self.assertRaises(
788 TypeError, context.set_passwd_cb, lambda: None, None, None
Hynek Schlawack2c013a92015-09-05 19:33:05 +0200789 ) # pragma: nocover
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400790
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400791 def test_set_passwd_cb(self):
792 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200793 :py:obj:`Context.set_passwd_cb` accepts a callable which will be
794 invoked when a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400795 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400796 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400797 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400798 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200799
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400800 def passphraseCallback(maxlen, verify, extra):
801 calledWith.append((maxlen, verify, extra))
802 return passphrase
803 context = Context(TLSv1_METHOD)
804 context.set_passwd_cb(passphraseCallback)
805 context.use_privatekey_file(pemFile)
806 self.assertTrue(len(calledWith), 1)
807 self.assertTrue(isinstance(calledWith[0][0], int))
808 self.assertTrue(isinstance(calledWith[0][1], int))
809 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400810
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400811 def test_passwd_callback_exception(self):
812 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200813 :py:obj:`Context.use_privatekey_file` propagates any exception raised
814 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400815 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400816 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200817
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400818 def passphraseCallback(maxlen, verify, extra):
819 raise RuntimeError("Sorry, I am a fail.")
820
821 context = Context(TLSv1_METHOD)
822 context.set_passwd_cb(passphraseCallback)
823 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
824
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400825 def test_passwd_callback_false(self):
826 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200827 :py:obj:`Context.use_privatekey_file` raises
828 :py:obj:`OpenSSL.SSL.Error` if the passphrase callback returns a false
829 value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400830 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400831 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200832
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400833 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500834 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400835
836 context = Context(TLSv1_METHOD)
837 context.set_passwd_cb(passphraseCallback)
838 self.assertRaises(Error, context.use_privatekey_file, pemFile)
839
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400840 def test_passwd_callback_non_string(self):
841 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200842 :py:obj:`Context.use_privatekey_file` raises
843 :py:obj:`OpenSSL.SSL.Error` if the passphrase callback returns a true
844 non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400845 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400846 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200847
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400848 def passphraseCallback(maxlen, verify, extra):
849 return 10
850
851 context = Context(TLSv1_METHOD)
852 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800853 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400854
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400855 def test_passwd_callback_too_long(self):
856 """
857 If the passphrase returned by the passphrase callback returns a string
858 longer than the indicated maximum length, it is truncated.
859 """
860 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400861 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400862 pemFile = self._write_encrypted_pem(passphrase)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200863
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400864 def passphraseCallback(maxlen, verify, extra):
865 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400866 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400867
868 context = Context(TLSv1_METHOD)
869 context.set_passwd_cb(passphraseCallback)
870 # This shall succeed because the truncated result is the correct
871 # passphrase.
872 context.use_privatekey_file(pemFile)
873
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400874 def test_set_info_callback(self):
875 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200876 :py:obj:`Context.set_info_callback` accepts a callable which will be
877 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400878 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500879 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400880
881 clientSSL = Connection(Context(TLSv1_METHOD), client)
882 clientSSL.set_connect_state()
883
884 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200885
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400886 def info(conn, where, ret):
887 called.append((conn, where, ret))
888 context = Context(TLSv1_METHOD)
889 context.set_info_callback(info)
890 context.use_certificate(
891 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
892 context.use_privatekey(
893 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
894
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400895 serverSSL = Connection(context, server)
896 serverSSL.set_accept_state()
897
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500898 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400899
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500900 # The callback must always be called with a Connection instance as the
901 # first argument. It would probably be better to split this into
902 # separate tests for client and server side info callbacks so we could
903 # assert it is called with the right Connection instance. It would
904 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500905 notConnections = [
906 conn for (conn, where, ret) in called
907 if not isinstance(conn, Connection)]
908 self.assertEqual(
909 [], notConnections,
910 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400911
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400912 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400913 """
914 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400915 its :py:obj:`load_verify_locations` method with the given arguments.
916 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400917 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500918 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400919
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400920 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400921 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400922 # Require that the server certificate verify properly or the
923 # connection will fail.
924 clientContext.set_verify(
925 VERIFY_PEER,
926 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
927
928 clientSSL = Connection(clientContext, client)
929 clientSSL.set_connect_state()
930
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400931 serverContext = Context(TLSv1_METHOD)
932 serverContext.use_certificate(
933 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
934 serverContext.use_privatekey(
935 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
936
937 serverSSL = Connection(serverContext, server)
938 serverSSL.set_accept_state()
939
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400940 # Without load_verify_locations above, the handshake
941 # will fail:
942 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
943 # 'certificate verify failed')]
944 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400945
946 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400947 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400948
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400949 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400950 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400951 Verify that if path to a file containing a certificate is passed to
952 ``Context.load_verify_locations`` for the ``cafile`` parameter, that
953 certificate is used as a trust root for the purposes of verifying
954 connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400955 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400956 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400957 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400958 fObj.close()
959
960 self._load_verify_locations_test(cafile)
961
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400962 def test_load_verify_bytes_cafile(self):
963 """
964 :py:obj:`Context.load_verify_locations` accepts a file name as a
965 ``bytes`` instance and uses the certificates within for verification
966 purposes.
967 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400968 cafile = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400969 self._load_verify_cafile(cafile)
970
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400971 def test_load_verify_unicode_cafile(self):
972 """
973 :py:obj:`Context.load_verify_locations` accepts a file name as a
974 ``unicode`` instance and uses the certificates within for verification
975 purposes.
976 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -0400977 self._load_verify_cafile(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400978 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -0400979 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400980
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400981 def test_load_verify_invalid_file(self):
982 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200983 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when
984 passed a non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400985 """
986 clientContext = Context(TLSv1_METHOD)
987 self.assertRaises(
988 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400989
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400990 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400991 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400992 Verify that if path to a directory containing certificate files is
993 passed to ``Context.load_verify_locations`` for the ``capath``
994 parameter, those certificates are used as trust roots for the purposes
995 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400996 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400997 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400998 # Hash values computed manually with c_rehash to avoid depending on
999 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1000 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001001 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001002 cafile = join_bytes_or_unicode(capath, name)
1003 with open(cafile, 'w') as fObj:
1004 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001005
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001006 self._load_verify_locations_test(None, capath)
1007
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001008 def test_load_verify_directory_bytes_capath(self):
1009 """
1010 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1011 ``bytes`` instance and uses the certificates within for verification
1012 purposes.
1013 """
1014 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001015 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001016 )
1017
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001018 def test_load_verify_directory_unicode_capath(self):
1019 """
1020 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1021 ``unicode`` instance and uses the certificates within for verification
1022 purposes.
1023 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001024 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001025 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001026 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001027
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001028 def test_load_verify_locations_wrong_args(self):
1029 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001030 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if
1031 called with the wrong number of arguments or with non-:py:obj:`str`
1032 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001033 """
1034 context = Context(TLSv1_METHOD)
1035 self.assertRaises(TypeError, context.load_verify_locations)
1036 self.assertRaises(TypeError, context.load_verify_locations, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001037 self.assertRaises(
1038 TypeError, context.load_verify_locations, object(), object()
1039 )
1040 self.assertRaises(
1041 TypeError, context.load_verify_locations, None, None, None
1042 )
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001043
Hynek Schlawack734d3022015-09-05 19:19:32 +02001044 @pytest.mark.skipif(
1045 platform == "win32",
1046 reason="set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001047 "See LP#404343 and LP#404344."
Hynek Schlawack734d3022015-09-05 19:19:32 +02001048 )
1049 def test_set_default_verify_paths(self):
1050 """
1051 :py:obj:`Context.set_default_verify_paths` causes the
1052 platform-specific CA certificate locations to be used for
1053 verification purposes.
1054 """
1055 # Testing this requires a server with a certificate signed by one
1056 # of the CAs in the platform CA location. Getting one of those
1057 # costs money. Fortunately (or unfortunately, depending on your
1058 # perspective), it's easy to think of a public server on the
1059 # internet which has such a certificate. Connecting to the network
1060 # in a unit test is bad, but it's the only way I can think of to
1061 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001062
Hynek Schlawack734d3022015-09-05 19:19:32 +02001063 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
1064 context = Context(TLSv1_METHOD)
1065 context.set_default_verify_paths()
1066 context.set_verify(
1067 VERIFY_PEER,
1068 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001069
Hynek Schlawack734d3022015-09-05 19:19:32 +02001070 client = socket()
1071 client.connect(('verisign.com', 443))
1072 clientSSL = Connection(context, client)
1073 clientSSL.set_connect_state()
1074 clientSSL.do_handshake()
1075 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
1076 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001077
1078 def test_set_default_verify_paths_signature(self):
1079 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001080 :py:obj:`Context.set_default_verify_paths` takes no arguments and
1081 raises :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001082 """
1083 context = Context(TLSv1_METHOD)
1084 self.assertRaises(TypeError, context.set_default_verify_paths, None)
1085 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
1086 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001087
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001088 def test_add_extra_chain_cert_invalid_cert(self):
1089 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001090 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if
1091 called with other than one argument or if called with an object which
1092 is not an instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001093 """
1094 context = Context(TLSv1_METHOD)
1095 self.assertRaises(TypeError, context.add_extra_chain_cert)
1096 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001097 self.assertRaises(
1098 TypeError, context.add_extra_chain_cert, object(), object()
1099 )
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001100
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001101 def _handshake_test(self, serverContext, clientContext):
1102 """
1103 Verify that a client and server created with the given contexts can
1104 successfully handshake and communicate.
1105 """
1106 serverSocket, clientSocket = socket_pair()
1107
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001108 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001109 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001110
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001111 client = Connection(clientContext, clientSocket)
1112 client.set_connect_state()
1113
1114 # Make them talk to each other.
1115 # self._interactInMemory(client, server)
1116 for i in range(3):
1117 for s in [client, server]:
1118 try:
1119 s.do_handshake()
1120 except WantReadError:
1121 pass
1122
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001123 def test_set_verify_callback_connection_argument(self):
1124 """
1125 The first argument passed to the verify callback is the
1126 :py:class:`Connection` instance for which verification is taking place.
1127 """
1128 serverContext = Context(TLSv1_METHOD)
1129 serverContext.use_privatekey(
1130 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1131 serverContext.use_certificate(
1132 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1133 serverConnection = Connection(serverContext, None)
1134
1135 class VerifyCallback(object):
1136 def callback(self, connection, *args):
1137 self.connection = connection
1138 return 1
1139
1140 verify = VerifyCallback()
1141 clientContext = Context(TLSv1_METHOD)
1142 clientContext.set_verify(VERIFY_PEER, verify.callback)
1143 clientConnection = Connection(clientContext, None)
1144 clientConnection.set_connect_state()
1145
1146 self._handshakeInMemory(clientConnection, serverConnection)
1147
1148 self.assertIdentical(verify.connection, clientConnection)
1149
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001150 def test_set_verify_callback_exception(self):
1151 """
1152 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1153 exception, verification fails and the exception is propagated to the
1154 caller of :py:obj:`Connection.do_handshake`.
1155 """
1156 serverContext = Context(TLSv1_METHOD)
1157 serverContext.use_privatekey(
1158 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1159 serverContext.use_certificate(
1160 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1161
1162 clientContext = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001163
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001164 def verify_callback(*args):
1165 raise Exception("silly verify failure")
1166 clientContext.set_verify(VERIFY_PEER, verify_callback)
1167
1168 exc = self.assertRaises(
1169 Exception, self._handshake_test, serverContext, clientContext)
1170 self.assertEqual("silly verify failure", str(exc))
1171
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001172 def test_add_extra_chain_cert(self):
1173 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001174 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509`
1175 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001176
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001177 See :py:obj:`_create_certificate_chain` for the details of the
1178 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001179
1180 The chain is tested by starting a server with scert and connecting
1181 to it with a client which trusts cacert and requires verification to
1182 succeed.
1183 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001184 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001185 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1186
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001187 # Dump the CA certificate to a file because that's the only way to load
1188 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001189 for cert, name in [(cacert, 'ca.pem'),
1190 (icert, 'i.pem'),
1191 (scert, 's.pem')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001192 with open(join(self.tmpdir, name), 'w') as f:
1193 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001194
Hynek Schlawack1902c012015-04-16 15:06:41 -04001195 for key, name in [(cakey, 'ca.key'),
1196 (ikey, 'i.key'),
1197 (skey, 's.key')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001198 with open(join(self.tmpdir, name), 'w') as f:
1199 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001200
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001201 # Create the server context
1202 serverContext = Context(TLSv1_METHOD)
1203 serverContext.use_privatekey(skey)
1204 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001205 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001206 serverContext.add_extra_chain_cert(icert)
1207
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001208 # Create the client
1209 clientContext = Context(TLSv1_METHOD)
1210 clientContext.set_verify(
1211 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001212 clientContext.load_verify_locations(join(self.tmpdir, "ca.pem"))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001213
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001214 # Try it out.
1215 self._handshake_test(serverContext, clientContext)
1216
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001217 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001218 """
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001219 Verify that :py:obj:`Context.use_certificate_chain_file` reads a
1220 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001221
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001222 The chain is tested by starting a server with scert and connecting to
1223 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001224 succeed.
1225 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001226 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001227 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1228
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001229 makedirs(certdir)
1230
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001231 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1232 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001233
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001234 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001235 with open(chainFile, 'wb') as fObj:
1236 # Most specific to least general.
1237 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1238 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1239 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1240
1241 with open(caFile, 'w') as fObj:
1242 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001243
1244 serverContext = Context(TLSv1_METHOD)
1245 serverContext.use_certificate_chain_file(chainFile)
1246 serverContext.use_privatekey(skey)
1247
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001248 clientContext = Context(TLSv1_METHOD)
1249 clientContext.set_verify(
1250 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001251 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001252
1253 self._handshake_test(serverContext, clientContext)
1254
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001255 def test_use_certificate_chain_file_bytes(self):
1256 """
1257 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1258 an instance of ``bytes``) to specify additional certificates to use to
1259 construct and verify a trust chain.
1260 """
1261 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001262 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001263 )
1264
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001265 def test_use_certificate_chain_file_unicode(self):
1266 """
1267 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1268 an instance of ``unicode``) to specify additional certificates to use
1269 to construct and verify a trust chain.
1270 """
1271 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001272 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001273 )
1274
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001275 def test_use_certificate_chain_file_wrong_args(self):
1276 """
1277 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1278 if passed zero or more than one argument or when passed a non-byte
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001279 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error`
1280 when passed a bad chain file name (for example, the name of a file
1281 which does not exist).
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001282 """
1283 context = Context(TLSv1_METHOD)
1284 self.assertRaises(TypeError, context.use_certificate_chain_file)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001285 self.assertRaises(
1286 TypeError, context.use_certificate_chain_file, object()
1287 )
1288 self.assertRaises(
1289 TypeError, context.use_certificate_chain_file, b"foo", object()
1290 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001291
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001292 self.assertRaises(
1293 Error, context.use_certificate_chain_file, self.mktemp()
1294 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001295
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001296 # XXX load_client_ca
1297 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001298
1299 def test_get_verify_mode_wrong_args(self):
1300 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001301 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called
1302 with any arguments.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001303 """
1304 context = Context(TLSv1_METHOD)
1305 self.assertRaises(TypeError, context.get_verify_mode, None)
1306
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001307 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001308 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001309 :py:obj:`Context.get_verify_mode` returns the verify mode flags
1310 previously passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001311 """
1312 context = Context(TLSv1_METHOD)
1313 self.assertEquals(context.get_verify_mode(), 0)
1314 context.set_verify(
1315 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1316 self.assertEquals(
1317 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1318
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001319 @skip_if_py3
1320 def test_set_verify_mode_long(self):
1321 """
1322 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1323 type :py:obj:`long` as well as :py:obj:`int`.
1324 """
1325 context = Context(TLSv1_METHOD)
1326 self.assertEquals(context.get_verify_mode(), 0)
1327 context.set_verify(
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001328 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None
1329 ) # pragma: nocover
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001330 self.assertEquals(
1331 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001332
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001333 def test_load_tmp_dh_wrong_args(self):
1334 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001335 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with
1336 the wrong number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001337 """
1338 context = Context(TLSv1_METHOD)
1339 self.assertRaises(TypeError, context.load_tmp_dh)
1340 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1341 self.assertRaises(TypeError, context.load_tmp_dh, object())
1342
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001343 def test_load_tmp_dh_missing_file(self):
1344 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001345 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the
1346 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001347 """
1348 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001349 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001350
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001351 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001352 """
1353 Verify that calling ``Context.load_tmp_dh`` with the given filename
1354 does not raise an exception.
1355 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001356 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001357 with open(dhfilename, "w") as dhfile:
1358 dhfile.write(dhparam)
1359
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001360 context.load_tmp_dh(dhfilename)
1361 # XXX What should I assert here? -exarkun
1362
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001363 def test_load_tmp_dh_bytes(self):
1364 """
1365 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1366 specified file (given as ``bytes``).
1367 """
1368 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001369 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001370 )
1371
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001372 def test_load_tmp_dh_unicode(self):
1373 """
1374 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1375 specified file (given as ``unicode``).
1376 """
1377 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001378 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001379 )
1380
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001381 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001382 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001383 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001384 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001385 """
1386 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001387 for curve in get_elliptic_curves():
1388 # The only easily "assertable" thing is that it does not raise an
1389 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001390 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001391
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001392 def test_set_cipher_list_bytes(self):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001393 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001394 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
1395 ciphers which connections created with the context object will be able
1396 to choose from.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001397 """
1398 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001399 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001400 conn = Connection(context, None)
1401 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001402
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001403 def test_set_cipher_list_text(self):
1404 """
1405 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
1406 the ciphers which connections created with the context object will be
1407 able to choose from.
1408 """
1409 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -05001410 context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001411 conn = Connection(context, None)
1412 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
1413
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001414 def test_set_cipher_list_wrong_args(self):
1415 """
Jean-Paul Calderone17044832014-01-18 10:20:11 -05001416 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
1417 passed zero arguments or more than one argument or when passed a
1418 non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001419 passed an incorrect cipher list string.
1420 """
1421 context = Context(TLSv1_METHOD)
1422 self.assertRaises(TypeError, context.set_cipher_list)
1423 self.assertRaises(TypeError, context.set_cipher_list, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001424 self.assertRaises(
1425 TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object()
1426 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001427
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001428 self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001429
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001430 def test_set_session_cache_mode_wrong_args(self):
1431 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001432 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1433 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001434 """
1435 context = Context(TLSv1_METHOD)
1436 self.assertRaises(TypeError, context.set_session_cache_mode)
1437 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1438
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001439 def test_get_session_cache_mode_wrong_args(self):
1440 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001441 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1442 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001443 """
1444 context = Context(TLSv1_METHOD)
1445 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1446
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001447 def test_session_cache_mode(self):
1448 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001449 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1450 cached. The setting can be retrieved via
1451 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001452 """
1453 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001454 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001455 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1456 self.assertEqual(SESS_CACHE_OFF, off)
1457 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1458
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001459 @skip_if_py3
1460 def test_session_cache_mode_long(self):
1461 """
1462 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1463 of type :py:obj:`long` as well as :py:obj:`int`.
1464 """
1465 context = Context(TLSv1_METHOD)
1466 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1467 self.assertEqual(
1468 SESS_CACHE_BOTH, context.get_session_cache_mode())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001469
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001470 def test_get_cert_store(self):
1471 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001472 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store`
1473 instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001474 """
1475 context = Context(TLSv1_METHOD)
1476 store = context.get_cert_store()
1477 self.assertIsInstance(store, X509Store)
1478
1479
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001480class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1481 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001482 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its
1483 interaction with :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001484 """
1485 def test_wrong_args(self):
1486 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001487 :py:obj:`Context.set_tlsext_servername_callback` raises
1488 :py:obj:`TypeError` if called with other than one argument.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001489 """
1490 context = Context(TLSv1_METHOD)
1491 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1492 self.assertRaises(
1493 TypeError, context.set_tlsext_servername_callback, 1, 2)
1494
1495 def test_old_callback_forgotten(self):
1496 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001497 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify
1498 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001499 """
1500 def callback(connection):
1501 pass
1502
1503 def replacement(connection):
1504 pass
1505
1506 context = Context(TLSv1_METHOD)
1507 context.set_tlsext_servername_callback(callback)
1508
1509 tracker = ref(callback)
1510 del callback
1511
1512 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001513
1514 # One run of the garbage collector happens to work on CPython. PyPy
1515 # doesn't collect the underlying object until a second run for whatever
1516 # reason. That's fine, it still demonstrates our code has properly
1517 # dropped the reference.
1518 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001519 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001520
1521 callback = tracker()
1522 if callback is not None:
1523 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001524 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001525 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001526
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001527 def test_no_servername(self):
1528 """
1529 When a client specifies no server name, the callback passed to
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001530 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the
1531 result of :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001532 """
1533 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001534
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001535 def servername(conn):
1536 args.append((conn, conn.get_servername()))
1537 context = Context(TLSv1_METHOD)
1538 context.set_tlsext_servername_callback(servername)
1539
1540 # Lose our reference to it. The Context is responsible for keeping it
1541 # alive now.
1542 del servername
1543 collect()
1544
1545 # Necessary to actually accept the connection
1546 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001547 context.use_certificate(
1548 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001549
1550 # Do a little connection to trigger the logic
1551 server = Connection(context, None)
1552 server.set_accept_state()
1553
1554 client = Connection(Context(TLSv1_METHOD), None)
1555 client.set_connect_state()
1556
1557 self._interactInMemory(server, client)
1558
1559 self.assertEqual([(server, None)], args)
1560
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001561 def test_servername(self):
1562 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001563 When a client specifies a server name in its hello message, the
1564 callback passed to :py:obj:`Contexts.set_tlsext_servername_callback` is
1565 invoked and the result of :py:obj:`Connection.get_servername` is that
1566 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001567 """
1568 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001569
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001570 def servername(conn):
1571 args.append((conn, conn.get_servername()))
1572 context = Context(TLSv1_METHOD)
1573 context.set_tlsext_servername_callback(servername)
1574
1575 # Necessary to actually accept the connection
1576 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001577 context.use_certificate(
1578 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001579
1580 # Do a little connection to trigger the logic
1581 server = Connection(context, None)
1582 server.set_accept_state()
1583
1584 client = Connection(Context(TLSv1_METHOD), None)
1585 client.set_connect_state()
1586 client.set_tlsext_host_name(b("foo1.example.com"))
1587
1588 self._interactInMemory(server, client)
1589
1590 self.assertEqual([(server, b("foo1.example.com"))], args)
1591
1592
Cory Benfield84a121e2014-03-31 20:30:25 +01001593class NextProtoNegotiationTests(TestCase, _LoopbackMixin):
1594 """
1595 Test for Next Protocol Negotiation in PyOpenSSL.
1596 """
Cory Benfieldba1820d2015-04-13 17:39:12 -04001597 if _lib.Cryptography_HAS_NEXTPROTONEG:
1598 def test_npn_success(self):
1599 """
1600 Tests that clients and servers that agree on the negotiated next
1601 protocol can correct establish a connection, and that the agreed
1602 protocol is reported by the connections.
1603 """
1604 advertise_args = []
1605 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001606
Cory Benfieldba1820d2015-04-13 17:39:12 -04001607 def advertise(conn):
1608 advertise_args.append((conn,))
1609 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001610
Cory Benfieldba1820d2015-04-13 17:39:12 -04001611 def select(conn, options):
1612 select_args.append((conn, options))
1613 return b'spdy/2'
Cory Benfield84a121e2014-03-31 20:30:25 +01001614
Cory Benfieldba1820d2015-04-13 17:39:12 -04001615 server_context = Context(TLSv1_METHOD)
1616 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001617
Cory Benfieldba1820d2015-04-13 17:39:12 -04001618 client_context = Context(TLSv1_METHOD)
1619 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001620
Cory Benfieldba1820d2015-04-13 17:39:12 -04001621 # Necessary to actually accept the connection
1622 server_context.use_privatekey(
1623 load_privatekey(FILETYPE_PEM, server_key_pem))
1624 server_context.use_certificate(
1625 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001626
Cory Benfieldba1820d2015-04-13 17:39:12 -04001627 # Do a little connection to trigger the logic
1628 server = Connection(server_context, None)
1629 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001630
Cory Benfieldba1820d2015-04-13 17:39:12 -04001631 client = Connection(client_context, None)
1632 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001633
Cory Benfieldba1820d2015-04-13 17:39:12 -04001634 self._interactInMemory(server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001635
Cory Benfieldba1820d2015-04-13 17:39:12 -04001636 self.assertEqual([(server,)], advertise_args)
1637 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001638
Cory Benfieldba1820d2015-04-13 17:39:12 -04001639 self.assertEqual(server.get_next_proto_negotiated(), b'spdy/2')
1640 self.assertEqual(client.get_next_proto_negotiated(), b'spdy/2')
Cory Benfield84a121e2014-03-31 20:30:25 +01001641
Cory Benfieldba1820d2015-04-13 17:39:12 -04001642 def test_npn_client_fail(self):
1643 """
1644 Tests that when clients and servers cannot agree on what protocol
1645 to use next that the TLS connection does not get established.
1646 """
1647 advertise_args = []
1648 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001649
Cory Benfieldba1820d2015-04-13 17:39:12 -04001650 def advertise(conn):
1651 advertise_args.append((conn,))
1652 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001653
Cory Benfieldba1820d2015-04-13 17:39:12 -04001654 def select(conn, options):
1655 select_args.append((conn, options))
1656 return b''
Cory Benfield84a121e2014-03-31 20:30:25 +01001657
Cory Benfieldba1820d2015-04-13 17:39:12 -04001658 server_context = Context(TLSv1_METHOD)
1659 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001660
Cory Benfieldba1820d2015-04-13 17:39:12 -04001661 client_context = Context(TLSv1_METHOD)
1662 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001663
Cory Benfieldba1820d2015-04-13 17:39:12 -04001664 # Necessary to actually accept the connection
1665 server_context.use_privatekey(
1666 load_privatekey(FILETYPE_PEM, server_key_pem))
1667 server_context.use_certificate(
1668 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001669
Cory Benfieldba1820d2015-04-13 17:39:12 -04001670 # Do a little connection to trigger the logic
1671 server = Connection(server_context, None)
1672 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001673
Cory Benfieldba1820d2015-04-13 17:39:12 -04001674 client = Connection(client_context, None)
1675 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001676
Cory Benfieldba1820d2015-04-13 17:39:12 -04001677 # If the client doesn't return anything, the connection will fail.
1678 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001679
Cory Benfieldba1820d2015-04-13 17:39:12 -04001680 self.assertEqual([(server,)], advertise_args)
1681 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001682
Cory Benfieldba1820d2015-04-13 17:39:12 -04001683 def test_npn_select_error(self):
1684 """
1685 Test that we can handle exceptions in the select callback. If
1686 select fails it should be fatal to the connection.
1687 """
1688 advertise_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001689
Cory Benfieldba1820d2015-04-13 17:39:12 -04001690 def advertise(conn):
1691 advertise_args.append((conn,))
1692 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001693
Cory Benfieldba1820d2015-04-13 17:39:12 -04001694 def select(conn, options):
1695 raise TypeError
Cory Benfield0ea76e72015-03-22 09:05:28 +00001696
Cory Benfieldba1820d2015-04-13 17:39:12 -04001697 server_context = Context(TLSv1_METHOD)
1698 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001699
Cory Benfieldba1820d2015-04-13 17:39:12 -04001700 client_context = Context(TLSv1_METHOD)
1701 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001702
Cory Benfieldba1820d2015-04-13 17:39:12 -04001703 # Necessary to actually accept the connection
1704 server_context.use_privatekey(
1705 load_privatekey(FILETYPE_PEM, server_key_pem))
1706 server_context.use_certificate(
1707 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001708
Cory Benfieldba1820d2015-04-13 17:39:12 -04001709 # Do a little connection to trigger the logic
1710 server = Connection(server_context, None)
1711 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001712
Cory Benfieldba1820d2015-04-13 17:39:12 -04001713 client = Connection(client_context, None)
1714 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001715
Cory Benfieldba1820d2015-04-13 17:39:12 -04001716 # If the callback throws an exception it should be raised here.
1717 self.assertRaises(
1718 TypeError, self._interactInMemory, server, client
1719 )
1720 self.assertEqual([(server,)], advertise_args)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001721
Cory Benfieldba1820d2015-04-13 17:39:12 -04001722 def test_npn_advertise_error(self):
1723 """
1724 Test that we can handle exceptions in the advertise callback. If
1725 advertise fails no NPN is advertised to the client.
1726 """
1727 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001728
Cory Benfieldba1820d2015-04-13 17:39:12 -04001729 def advertise(conn):
1730 raise TypeError
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001731
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001732 def select(conn, options): # pragma: nocover
1733 """
1734 Assert later that no args are actually appended.
1735 """
Cory Benfieldba1820d2015-04-13 17:39:12 -04001736 select_args.append((conn, options))
1737 return b''
Cory Benfield0ea76e72015-03-22 09:05:28 +00001738
Cory Benfieldba1820d2015-04-13 17:39:12 -04001739 server_context = Context(TLSv1_METHOD)
1740 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001741
Cory Benfieldba1820d2015-04-13 17:39:12 -04001742 client_context = Context(TLSv1_METHOD)
1743 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001744
Cory Benfieldba1820d2015-04-13 17:39:12 -04001745 # Necessary to actually accept the connection
1746 server_context.use_privatekey(
1747 load_privatekey(FILETYPE_PEM, server_key_pem))
1748 server_context.use_certificate(
1749 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001750
Cory Benfieldba1820d2015-04-13 17:39:12 -04001751 # Do a little connection to trigger the logic
1752 server = Connection(server_context, None)
1753 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001754
Cory Benfieldba1820d2015-04-13 17:39:12 -04001755 client = Connection(client_context, None)
1756 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001757
Cory Benfieldba1820d2015-04-13 17:39:12 -04001758 # If the client doesn't return anything, the connection will fail.
1759 self.assertRaises(
1760 TypeError, self._interactInMemory, server, client
1761 )
1762 self.assertEqual([], select_args)
1763
1764 else:
1765 # No NPN.
1766 def test_npn_not_implemented(self):
1767 # Test the context methods first.
1768 context = Context(TLSv1_METHOD)
1769 fail_methods = [
1770 context.set_npn_advertise_callback,
1771 context.set_npn_select_callback,
1772 ]
1773 for method in fail_methods:
1774 self.assertRaises(
1775 NotImplementedError, method, None
1776 )
1777
1778 # Now test a connection.
1779 conn = Connection(context)
1780 fail_methods = [
1781 conn.get_next_proto_negotiated,
1782 ]
1783 for method in fail_methods:
1784 self.assertRaises(NotImplementedError, method)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001785
1786
Cory Benfield12eae892014-06-07 15:42:56 +01001787class ApplicationLayerProtoNegotiationTests(TestCase, _LoopbackMixin):
1788 """
1789 Tests for ALPN in PyOpenSSL.
1790 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001791 # Skip tests on versions that don't support ALPN.
1792 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001793
Cory Benfielde46fa842015-04-13 16:50:49 -04001794 def test_alpn_success(self):
1795 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001796 Clients and servers that agree on the negotiated ALPN protocol can
1797 correct establish a connection, and the agreed protocol is reported
1798 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001799 """
1800 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001801
Cory Benfielde46fa842015-04-13 16:50:49 -04001802 def select(conn, options):
1803 select_args.append((conn, options))
1804 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001805
Cory Benfielde46fa842015-04-13 16:50:49 -04001806 client_context = Context(TLSv1_METHOD)
1807 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001808
Cory Benfielde46fa842015-04-13 16:50:49 -04001809 server_context = Context(TLSv1_METHOD)
1810 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001811
Cory Benfielde46fa842015-04-13 16:50:49 -04001812 # Necessary to actually accept the connection
1813 server_context.use_privatekey(
1814 load_privatekey(FILETYPE_PEM, server_key_pem))
1815 server_context.use_certificate(
1816 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001817
Cory Benfielde46fa842015-04-13 16:50:49 -04001818 # Do a little connection to trigger the logic
1819 server = Connection(server_context, None)
1820 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001821
Cory Benfielde46fa842015-04-13 16:50:49 -04001822 client = Connection(client_context, None)
1823 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001824
Cory Benfielde46fa842015-04-13 16:50:49 -04001825 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001826
Cory Benfielde46fa842015-04-13 16:50:49 -04001827 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
1828
1829 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1830 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001831
Cory Benfielde46fa842015-04-13 16:50:49 -04001832 def test_alpn_set_on_connection(self):
1833 """
1834 The same as test_alpn_success, but setting the ALPN protocols on
1835 the connection rather than the context.
1836 """
1837 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001838
Cory Benfielde46fa842015-04-13 16:50:49 -04001839 def select(conn, options):
1840 select_args.append((conn, options))
1841 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001842
Cory Benfielde46fa842015-04-13 16:50:49 -04001843 # Setup the client context but don't set any ALPN protocols.
1844 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001845
Cory Benfielde46fa842015-04-13 16:50:49 -04001846 server_context = Context(TLSv1_METHOD)
1847 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001848
Cory Benfielde46fa842015-04-13 16:50:49 -04001849 # Necessary to actually accept the connection
1850 server_context.use_privatekey(
1851 load_privatekey(FILETYPE_PEM, server_key_pem))
1852 server_context.use_certificate(
1853 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001854
Cory Benfielde46fa842015-04-13 16:50:49 -04001855 # Do a little connection to trigger the logic
1856 server = Connection(server_context, None)
1857 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001858
Cory Benfielde46fa842015-04-13 16:50:49 -04001859 # Set the ALPN protocols on the client connection.
1860 client = Connection(client_context, None)
1861 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1862 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001863
Cory Benfielde46fa842015-04-13 16:50:49 -04001864 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001865
Cory Benfielde46fa842015-04-13 16:50:49 -04001866 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001867
Cory Benfielde46fa842015-04-13 16:50:49 -04001868 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1869 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001870
Cory Benfielde46fa842015-04-13 16:50:49 -04001871 def test_alpn_server_fail(self):
1872 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001873 When clients and servers cannot agree on what protocol to use next
1874 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001875 """
1876 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001877
Cory Benfielde46fa842015-04-13 16:50:49 -04001878 def select(conn, options):
1879 select_args.append((conn, options))
1880 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001881
Cory Benfielde46fa842015-04-13 16:50:49 -04001882 client_context = Context(TLSv1_METHOD)
1883 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001884
Cory Benfielde46fa842015-04-13 16:50:49 -04001885 server_context = Context(TLSv1_METHOD)
1886 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001887
Cory Benfielde46fa842015-04-13 16:50:49 -04001888 # Necessary to actually accept the connection
1889 server_context.use_privatekey(
1890 load_privatekey(FILETYPE_PEM, server_key_pem))
1891 server_context.use_certificate(
1892 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001893
Cory Benfielde46fa842015-04-13 16:50:49 -04001894 # Do a little connection to trigger the logic
1895 server = Connection(server_context, None)
1896 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001897
Cory Benfielde46fa842015-04-13 16:50:49 -04001898 client = Connection(client_context, None)
1899 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001900
Cory Benfielde46fa842015-04-13 16:50:49 -04001901 # If the client doesn't return anything, the connection will fail.
1902 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001903
Cory Benfielde46fa842015-04-13 16:50:49 -04001904 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001905
Cory Benfielde46fa842015-04-13 16:50:49 -04001906 def test_alpn_no_server(self):
1907 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001908 When clients and servers cannot agree on what protocol to use next
1909 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04001910 """
1911 client_context = Context(TLSv1_METHOD)
1912 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04001913
Cory Benfielde46fa842015-04-13 16:50:49 -04001914 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04001915
Cory Benfielde46fa842015-04-13 16:50:49 -04001916 # Necessary to actually accept the connection
1917 server_context.use_privatekey(
1918 load_privatekey(FILETYPE_PEM, server_key_pem))
1919 server_context.use_certificate(
1920 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04001921
Cory Benfielde46fa842015-04-13 16:50:49 -04001922 # Do a little connection to trigger the logic
1923 server = Connection(server_context, None)
1924 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001925
Cory Benfielde46fa842015-04-13 16:50:49 -04001926 client = Connection(client_context, None)
1927 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001928
Cory Benfielde46fa842015-04-13 16:50:49 -04001929 # Do the dance.
1930 self._interactInMemory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04001931
Cory Benfielde46fa842015-04-13 16:50:49 -04001932 self.assertEqual(client.get_alpn_proto_negotiated(), b'')
Cory Benfielde3d57152015-04-11 17:57:35 -04001933
Cory Benfielde46fa842015-04-13 16:50:49 -04001934 def test_alpn_callback_exception(self):
1935 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001936 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04001937 """
1938 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001939
Cory Benfielde46fa842015-04-13 16:50:49 -04001940 def select(conn, options):
1941 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04001942 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001943
Cory Benfielde46fa842015-04-13 16:50:49 -04001944 client_context = Context(TLSv1_METHOD)
1945 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04001946
Cory Benfielde46fa842015-04-13 16:50:49 -04001947 server_context = Context(TLSv1_METHOD)
1948 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04001949
Cory Benfielde46fa842015-04-13 16:50:49 -04001950 # Necessary to actually accept the connection
1951 server_context.use_privatekey(
1952 load_privatekey(FILETYPE_PEM, server_key_pem))
1953 server_context.use_certificate(
1954 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04001955
Cory Benfielde46fa842015-04-13 16:50:49 -04001956 # Do a little connection to trigger the logic
1957 server = Connection(server_context, None)
1958 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001959
Cory Benfielde46fa842015-04-13 16:50:49 -04001960 client = Connection(client_context, None)
1961 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001962
Cory Benfielde46fa842015-04-13 16:50:49 -04001963 self.assertRaises(
1964 TypeError, self._interactInMemory, server, client
1965 )
1966 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfieldf1177e72015-04-12 09:11:49 -04001967
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001968 else:
1969 # No ALPN.
1970 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04001971 """
1972 If ALPN is not in OpenSSL, we should raise NotImplementedError.
1973 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001974 # Test the context methods first.
1975 context = Context(TLSv1_METHOD)
Cory Benfield307e9e62015-04-13 18:21:12 -04001976 self.assertRaises(
1977 NotImplementedError, context.set_alpn_protos, None
1978 )
1979 self.assertRaises(
1980 NotImplementedError, context.set_alpn_select_callback, None
1981 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001982
1983 # Now test a connection.
1984 conn = Connection(context)
Cory Benfield307e9e62015-04-13 18:21:12 -04001985 self.assertRaises(
Alex Gaynor68417232015-09-04 07:56:29 -04001986 NotImplementedError, conn.set_alpn_protos, None
Cory Benfield307e9e62015-04-13 18:21:12 -04001987 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001988
Cory Benfieldf1177e72015-04-12 09:11:49 -04001989
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001990class SessionTests(TestCase):
1991 """
1992 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1993 """
1994 def test_construction(self):
1995 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001996 :py:class:`Session` can be constructed with no arguments, creating
1997 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001998 """
1999 new_session = Session()
2000 self.assertTrue(isinstance(new_session, Session))
2001
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002002 def test_construction_wrong_args(self):
2003 """
2004 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
2005 is raised.
2006 """
2007 self.assertRaises(TypeError, Session, 123)
2008 self.assertRaises(TypeError, Session, "hello")
2009 self.assertRaises(TypeError, Session, object())
2010
2011
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002012class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05002013 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002014 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002015 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002016 # XXX get_peer_certificate -> None
2017 # XXX sock_shutdown
2018 # XXX master_key -> TypeError
2019 # XXX server_random -> TypeError
2020 # XXX state_string
2021 # XXX connect -> TypeError
2022 # XXX connect_ex -> TypeError
2023 # XXX set_connect_state -> TypeError
2024 # XXX set_accept_state -> TypeError
2025 # XXX renegotiate_pending
2026 # XXX do_handshake -> TypeError
2027 # XXX bio_read -> TypeError
2028 # XXX recv -> TypeError
2029 # XXX send -> TypeError
2030 # XXX bio_write -> TypeError
2031
Rick Deane15b1472009-07-09 15:53:42 -05002032 def test_type(self):
2033 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002034 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same
2035 type object and can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002036 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002037 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05002038 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002039 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002040
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002041 def test_get_context(self):
2042 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002043 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance
2044 used to construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002045 """
2046 context = Context(TLSv1_METHOD)
2047 connection = Connection(context, None)
2048 self.assertIdentical(connection.get_context(), context)
2049
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002050 def test_get_context_wrong_args(self):
2051 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002052 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called
2053 with any arguments.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002054 """
2055 connection = Connection(Context(TLSv1_METHOD), None)
2056 self.assertRaises(TypeError, connection.get_context, None)
2057
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002058 def test_set_context_wrong_args(self):
2059 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002060 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called
2061 with a non-:py:obj:`Context` instance argument or with any number of
2062 arguments other than 1.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002063 """
2064 ctx = Context(TLSv1_METHOD)
2065 connection = Connection(ctx, None)
2066 self.assertRaises(TypeError, connection.set_context)
2067 self.assertRaises(TypeError, connection.set_context, object())
2068 self.assertRaises(TypeError, connection.set_context, "hello")
2069 self.assertRaises(TypeError, connection.set_context, 1)
2070 self.assertRaises(TypeError, connection.set_context, 1, 2)
2071 self.assertRaises(
2072 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
2073 self.assertIdentical(ctx, connection.get_context())
2074
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002075 def test_set_context(self):
2076 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002077 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context`
2078 instance to be used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002079 """
2080 original = Context(SSLv23_METHOD)
2081 replacement = Context(TLSv1_METHOD)
2082 connection = Connection(original, None)
2083 connection.set_context(replacement)
2084 self.assertIdentical(replacement, connection.get_context())
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002085 # Lose our references to the contexts, just in case the Connection
2086 # isn't properly managing its own contributions to their reference
2087 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002088 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002089 collect()
2090
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002091 def test_set_tlsext_host_name_wrong_args(self):
2092 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002093 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte
2094 string argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09002095 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002096 """
2097 conn = Connection(Context(TLSv1_METHOD), None)
2098 self.assertRaises(TypeError, conn.set_tlsext_host_name)
2099 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
2100 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
2101 self.assertRaises(
2102 TypeError, conn.set_tlsext_host_name, b("with\0null"))
2103
Abraham Martinc5484ba2015-03-25 15:33:05 +00002104 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002105 # On Python 3.x, don't accidentally implicitly convert from text.
2106 self.assertRaises(
2107 TypeError,
2108 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002109
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002110 def test_get_servername_wrong_args(self):
2111 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002112 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if
2113 called with any arguments.
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002114 """
2115 connection = Connection(Context(TLSv1_METHOD), None)
2116 self.assertRaises(TypeError, connection.get_servername, object())
2117 self.assertRaises(TypeError, connection.get_servername, 1)
2118 self.assertRaises(TypeError, connection.get_servername, "hello")
2119
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002120 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002121 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002122 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002123 immediate read.
2124 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002125 connection = Connection(Context(TLSv1_METHOD), None)
2126 self.assertEquals(connection.pending(), 0)
2127
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002128 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002129 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002130 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with
2131 any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002132 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002133 connection = Connection(Context(TLSv1_METHOD), None)
2134 self.assertRaises(TypeError, connection.pending, None)
2135
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002136 def test_peek(self):
2137 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002138 :py:obj:`Connection.recv` peeks into the connection if
2139 :py:obj:`socket.MSG_PEEK` is passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002140 """
2141 server, client = self._loopback()
2142 server.send(b('xy'))
2143 self.assertEqual(client.recv(2, MSG_PEEK), b('xy'))
2144 self.assertEqual(client.recv(2, MSG_PEEK), b('xy'))
2145 self.assertEqual(client.recv(2), b('xy'))
2146
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002147 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002148 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002149 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with
2150 a non-address argument or with the wrong number of arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002151 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002152 connection = Connection(Context(TLSv1_METHOD), socket())
2153 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002154 self.assertRaises(TypeError, connection.connect)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002155 self.assertRaises(
2156 TypeError, connection.connect, ("127.0.0.1", 1), None
2157 )
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002158
kjavfe508d62015-09-02 12:20:35 +01002159 def test_connection_undefined_attr(self):
2160 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002161 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with
2162 a non-address argument or with the wrong number of arguments.
kjavfe508d62015-09-02 12:20:35 +01002163 """
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002164
kjavfe508d62015-09-02 12:20:35 +01002165 def attr_access_test(connection):
2166 return connection.an_attribute_which_is_not_defined
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002167
kjavfe508d62015-09-02 12:20:35 +01002168 connection = Connection(Context(TLSv1_METHOD), None)
2169 self.assertRaises(AttributeError, attr_access_test, connection)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002170
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002171 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002172 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002173 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the
2174 underlying socket connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002175 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002176 client = socket()
2177 context = Context(TLSv1_METHOD)
2178 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002179 # pytest.raises here doesn't work because of a bug in py.test on Python
2180 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002181 try:
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002182 clientSSL.connect(("127.0.0.1", 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002183 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002184 exc = e
2185 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002186
2187 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002188 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002189 :py:obj:`Connection.connect` establishes a connection to the specified
2190 address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002191 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002192 port = socket()
2193 port.bind(('', 0))
2194 port.listen(3)
2195
2196 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002197 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2198 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002199
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002200 @pytest.mark.skipif(
2201 platform == "darwin",
2202 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2203 )
2204 def test_connect_ex(self):
2205 """
2206 If there is a connection error, :py:obj:`Connection.connect_ex`
2207 returns the errno instead of raising an exception.
2208 """
2209 port = socket()
2210 port.bind(('', 0))
2211 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002212
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002213 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2214 clientSSL.setblocking(False)
2215 result = clientSSL.connect_ex(port.getsockname())
2216 expected = (EINPROGRESS, EWOULDBLOCK)
2217 self.assertTrue(
2218 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002219
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002220 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002221 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002222 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with
2223 any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002224 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002225 connection = Connection(Context(TLSv1_METHOD), socket())
2226 self.assertRaises(TypeError, connection.accept, None)
2227
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002228 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002229 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002230 :py:obj:`Connection.accept` accepts a pending connection attempt and
2231 returns a tuple of a new :py:obj:`Connection` (the accepted client) and
2232 the address the connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002233 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002234 ctx = Context(TLSv1_METHOD)
2235 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2236 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002237 port = socket()
2238 portSSL = Connection(ctx, port)
2239 portSSL.bind(('', 0))
2240 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002241
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002242 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002243
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002244 # Calling portSSL.getsockname() here to get the server IP address
2245 # sounds great, but frequently fails on Windows.
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002246 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002247
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002248 serverSSL, address = portSSL.accept()
2249
2250 self.assertTrue(isinstance(serverSSL, Connection))
2251 self.assertIdentical(serverSSL.get_context(), ctx)
2252 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002253
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002254 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002255 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002256 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with
2257 the wrong number of arguments or with arguments other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002258 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002259 connection = Connection(Context(TLSv1_METHOD), None)
2260 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04002261 self.assertRaises(TypeError, connection.get_shutdown, None)
2262 self.assertRaises(TypeError, connection.set_shutdown)
2263 self.assertRaises(TypeError, connection.set_shutdown, None)
2264 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002265
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002266 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002267 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002268 :py:obj:`Connection.shutdown` performs an SSL-level connection
2269 shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002270 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002271 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002272 self.assertFalse(server.shutdown())
2273 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002274 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002275 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
2276 client.shutdown()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002277 self.assertEquals(
2278 client.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN
2279 )
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002280 self.assertRaises(ZeroReturnError, server.recv, 1024)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002281 self.assertEquals(
2282 server.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN
2283 )
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002284
Paul Aurichc85e0862015-01-08 08:34:33 -08002285 def test_shutdown_closed(self):
2286 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002287 If the underlying socket is closed, :py:obj:`Connection.shutdown`
2288 propagates the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002289 """
2290 server, client = self._loopback()
2291 server.sock_shutdown(2)
2292 exc = self.assertRaises(SysCallError, server.shutdown)
2293 if platform == "win32":
2294 self.assertEqual(exc.args[0], ESHUTDOWN)
2295 else:
2296 self.assertEqual(exc.args[0], EPIPE)
2297
Glyph89389472015-04-14 17:29:26 -04002298 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002299 """
Glyph89389472015-04-14 17:29:26 -04002300 If the underlying connection is truncated, :obj:`Connection.shutdown`
2301 raises an :obj:`Error`.
Glyph6064ec32015-04-14 16:38:22 -04002302 """
Glyph89389472015-04-14 17:29:26 -04002303 server_ctx = Context(TLSv1_METHOD)
2304 client_ctx = Context(TLSv1_METHOD)
2305 server_ctx.use_privatekey(
2306 load_privatekey(FILETYPE_PEM, server_key_pem))
2307 server_ctx.use_certificate(
2308 load_certificate(FILETYPE_PEM, server_cert_pem))
2309 server = Connection(server_ctx, None)
2310 client = Connection(client_ctx, None)
2311 self._handshakeInMemory(client, server)
2312 self.assertEqual(server.shutdown(), False)
2313 self.assertRaises(WantReadError, server.shutdown)
2314 server.bio_shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002315 self.assertRaises(Error, server.shutdown)
2316
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002317 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002318 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002319 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection
2320 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002321 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002322 connection = Connection(Context(TLSv1_METHOD), socket())
2323 connection.set_shutdown(RECEIVED_SHUTDOWN)
2324 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2325
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002326 @skip_if_py3
2327 def test_set_shutdown_long(self):
2328 """
2329 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
2330 of type :py:obj:`long` as well as :py:obj:`int`.
2331 """
2332 connection = Connection(Context(TLSv1_METHOD), socket())
2333 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
2334 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002335
kjavaf248592015-09-07 12:14:01 +01002336 def test_state_string(self):
2337 """
2338 :py:obj:`Connection.state_string` verbosely describes the current
2339 state of the :py:obj:`Connection`.
2340 """
2341 (server, client) = socket_pair()
2342 server = self._loopbackServerFactory(server)
2343 client = self._loopbackClientFactory(client)
2344
2345 self.assertEqual('before/accept initialization',
2346 server.state_string().decode())
2347 self.assertEqual('before/connect initialization',
2348 client.state_string().decode())
2349
2350 for conn in [server, client]:
2351 try:
2352 conn.do_handshake()
2353 except WantReadError:
2354 pass
2355
2356 self.assertEqual('SSLv3 read client hello B',
kjav3178c162015-09-07 12:23:09 +01002357 server.state_string().decode())
kjavaf248592015-09-07 12:14:01 +01002358 self.assertEqual('SSLv3 read server hello A',
2359 client.state_string().decode())
2360
2361 for conn in [server, client]:
2362 try:
2363 conn.do_handshake()
2364 except WantReadError:
2365 pass
2366
2367 self.assertEqual('SSLv3 read client certificate A',
2368 server.state_string().decode())
2369 self.assertEqual('SSLv3 read server session ticket A',
2370 client.state_string().decode())
2371
2372 for conn in [server, client]:
2373 try:
2374 conn.do_handshake()
2375 except WantReadError:
2376 pass
2377
2378 self.assertEqual('SSL negotiation finished successfully',
2379 server.state_string().decode())
2380 self.assertEqual('SSL negotiation finished successfully',
2381 client.state_string().decode())
2382
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002383 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002384 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002385 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called
2386 with other than one argument. :py:obj:`Connection.get_app_data` raises
2387 :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002388 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002389 conn = Connection(Context(TLSv1_METHOD), None)
2390 self.assertRaises(TypeError, conn.get_app_data, None)
2391 self.assertRaises(TypeError, conn.set_app_data)
2392 self.assertRaises(TypeError, conn.set_app_data, None, None)
2393
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002394 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002395 """
2396 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002397 :py:obj:`Connection.set_app_data` and later retrieved with
2398 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002399 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002400 conn = Connection(Context(TLSv1_METHOD), None)
2401 app_data = object()
2402 conn.set_app_data(app_data)
2403 self.assertIdentical(conn.get_app_data(), app_data)
2404
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002405 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002406 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002407 :py:obj:`Connection.makefile` is not implemented and calling that
2408 method raises :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002409 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002410 conn = Connection(Context(TLSv1_METHOD), None)
2411 self.assertRaises(NotImplementedError, conn.makefile)
2412
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002413 def test_get_peer_cert_chain_wrong_args(self):
2414 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002415 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if
2416 called with any arguments.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002417 """
2418 conn = Connection(Context(TLSv1_METHOD), None)
2419 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
2420 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
2421 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
2422 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
2423
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002424 def test_get_peer_cert_chain(self):
2425 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002426 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates
2427 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002428 """
2429 chain = _create_certificate_chain()
2430 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2431
2432 serverContext = Context(TLSv1_METHOD)
2433 serverContext.use_privatekey(skey)
2434 serverContext.use_certificate(scert)
2435 serverContext.add_extra_chain_cert(icert)
2436 serverContext.add_extra_chain_cert(cacert)
2437 server = Connection(serverContext, None)
2438 server.set_accept_state()
2439
2440 # Create the client
2441 clientContext = Context(TLSv1_METHOD)
2442 clientContext.set_verify(VERIFY_NONE, verify_cb)
2443 client = Connection(clientContext, None)
2444 client.set_connect_state()
2445
2446 self._interactInMemory(client, server)
2447
2448 chain = client.get_peer_cert_chain()
2449 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002450 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002451 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002452 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002453 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002454 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002455 "Authority Certificate", chain[2].get_subject().CN)
2456
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002457 def test_get_peer_cert_chain_none(self):
2458 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002459 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the
2460 peer sends no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002461 """
2462 ctx = Context(TLSv1_METHOD)
2463 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2464 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2465 server = Connection(ctx, None)
2466 server.set_accept_state()
2467 client = Connection(Context(TLSv1_METHOD), None)
2468 client.set_connect_state()
2469 self._interactInMemory(client, server)
2470 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002471
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002472 def test_get_session_wrong_args(self):
2473 """
2474 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
2475 with any arguments.
2476 """
2477 ctx = Context(TLSv1_METHOD)
2478 server = Connection(ctx, None)
2479 self.assertRaises(TypeError, server.get_session, 123)
2480 self.assertRaises(TypeError, server.get_session, "hello")
2481 self.assertRaises(TypeError, server.get_session, object())
2482
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002483 def test_get_session_unconnected(self):
2484 """
2485 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
2486 an object which has not been connected.
2487 """
2488 ctx = Context(TLSv1_METHOD)
2489 server = Connection(ctx, None)
2490 session = server.get_session()
2491 self.assertIdentical(None, session)
2492
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002493 def test_server_get_session(self):
2494 """
2495 On the server side of a connection, :py:obj:`Connection.get_session`
2496 returns a :py:class:`Session` instance representing the SSL session for
2497 that connection.
2498 """
2499 server, client = self._loopback()
2500 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002501 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002502
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002503 def test_client_get_session(self):
2504 """
2505 On the client side of a connection, :py:obj:`Connection.get_session`
2506 returns a :py:class:`Session` instance representing the SSL session for
2507 that connection.
2508 """
2509 server, client = self._loopback()
2510 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002511 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002512
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002513 def test_set_session_wrong_args(self):
2514 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002515 If called with an object that is not an instance of
2516 :py:class:`Session`, or with other than one argument,
2517 :py:obj:`Connection.set_session` raises :py:obj:`TypeError`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002518 """
2519 ctx = Context(TLSv1_METHOD)
2520 connection = Connection(ctx, None)
2521 self.assertRaises(TypeError, connection.set_session)
2522 self.assertRaises(TypeError, connection.set_session, 123)
2523 self.assertRaises(TypeError, connection.set_session, "hello")
2524 self.assertRaises(TypeError, connection.set_session, object())
2525 self.assertRaises(
2526 TypeError, connection.set_session, Session(), Session())
2527
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002528 def test_client_set_session(self):
2529 """
2530 :py:obj:`Connection.set_session`, when used prior to a connection being
2531 established, accepts a :py:class:`Session` instance and causes an
2532 attempt to re-use the session it represents when the SSL handshake is
2533 performed.
2534 """
2535 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2536 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2537 ctx = Context(TLSv1_METHOD)
2538 ctx.use_privatekey(key)
2539 ctx.use_certificate(cert)
2540 ctx.set_session_id("unity-test")
2541
2542 def makeServer(socket):
2543 server = Connection(ctx, socket)
2544 server.set_accept_state()
2545 return server
2546
2547 originalServer, originalClient = self._loopback(
2548 serverFactory=makeServer)
2549 originalSession = originalClient.get_session()
2550
2551 def makeClient(socket):
2552 client = self._loopbackClientFactory(socket)
2553 client.set_session(originalSession)
2554 return client
2555 resumedServer, resumedClient = self._loopback(
2556 serverFactory=makeServer,
2557 clientFactory=makeClient)
2558
2559 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002560 # identifier for the session (new enough versions of OpenSSL expose
2561 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002562 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002563 # session is re-used. As long as the master key for the two
2564 # connections is the same, the session was re-used!
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002565 self.assertEqual(
2566 originalServer.master_key(), resumedServer.master_key())
2567
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002568 def test_set_session_wrong_method(self):
2569 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002570 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002571 instance associated with a context using a different SSL method than
2572 the :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002573 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002574 """
2575 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2576 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2577 ctx = Context(TLSv1_METHOD)
2578 ctx.use_privatekey(key)
2579 ctx.use_certificate(cert)
2580 ctx.set_session_id("unity-test")
2581
2582 def makeServer(socket):
2583 server = Connection(ctx, socket)
2584 server.set_accept_state()
2585 return server
2586
2587 originalServer, originalClient = self._loopback(
2588 serverFactory=makeServer)
2589 originalSession = originalClient.get_session()
2590
2591 def makeClient(socket):
2592 # Intentionally use a different, incompatible method here.
2593 client = Connection(Context(SSLv3_METHOD), socket)
2594 client.set_connect_state()
2595 client.set_session(originalSession)
2596 return client
2597
2598 self.assertRaises(
2599 Error,
2600 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2601
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002602 def test_wantWriteError(self):
2603 """
2604 :py:obj:`Connection` methods which generate output raise
2605 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2606 fail indicating a should-write state.
2607 """
2608 client_socket, server_socket = socket_pair()
2609 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002610 # anything. Only write a single byte at a time so we can be sure we
2611 # completely fill the buffer. Even though the socket API is allowed to
2612 # signal a short write via its return value it seems this doesn't
2613 # always happen on all platforms (FreeBSD and OS X particular) for the
2614 # very last bit of available buffer space.
2615 msg = b"x"
2616 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002617 try:
2618 client_socket.send(msg)
2619 except error as e:
2620 if e.errno == EWOULDBLOCK:
2621 break
2622 raise
2623 else:
2624 self.fail(
2625 "Failed to fill socket buffer, cannot test BIO want write")
2626
2627 ctx = Context(TLSv1_METHOD)
2628 conn = Connection(ctx, client_socket)
2629 # Client's speak first, so make it an SSL client
2630 conn.set_connect_state()
2631 self.assertRaises(WantWriteError, conn.do_handshake)
2632
2633 # XXX want_read
2634
Fedor Brunner416f4a12014-03-28 13:18:38 +01002635 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002636 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002637 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2638 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002639 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002640 ctx = Context(TLSv1_METHOD)
2641 connection = Connection(ctx, None)
2642 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002643
2644 def test_get_peer_finished_before_connect(self):
2645 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002646 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2647 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002648 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002649 ctx = Context(TLSv1_METHOD)
2650 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002651 self.assertEqual(connection.get_peer_finished(), None)
2652
Fedor Brunner416f4a12014-03-28 13:18:38 +01002653 def test_get_finished(self):
2654 """
2655 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002656 message send from client, or server. Finished messages are send during
2657 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002658 """
2659
Fedor Brunner5747b932014-03-05 14:22:34 +01002660 server, client = self._loopback()
2661
2662 self.assertNotEqual(server.get_finished(), None)
2663 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002664
2665 def test_get_peer_finished(self):
2666 """
2667 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002668 message received from client, or server. Finished messages are send
2669 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002670 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002671 server, client = self._loopback()
2672
2673 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002674 self.assertTrue(len(server.get_peer_finished()) > 0)
2675
Fedor Brunner416f4a12014-03-28 13:18:38 +01002676 def test_tls_finished_message_symmetry(self):
2677 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002678 The TLS Finished message send by server must be the TLS Finished
2679 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002680
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002681 The TLS Finished message send by client must be the TLS Finished
2682 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002683 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002684 server, client = self._loopback()
2685
Fedor Brunner5747b932014-03-05 14:22:34 +01002686 self.assertEqual(server.get_finished(), client.get_peer_finished())
2687 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002688
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002689 def test_get_cipher_name_before_connect(self):
2690 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002691 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2692 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002693 """
2694 ctx = Context(TLSv1_METHOD)
2695 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002696 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002697
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002698 def test_get_cipher_name(self):
2699 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002700 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2701 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002702 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002703 server, client = self._loopback()
2704 server_cipher_name, client_cipher_name = \
2705 server.get_cipher_name(), client.get_cipher_name()
2706
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002707 self.assertIsInstance(server_cipher_name, text_type)
2708 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002709
2710 self.assertEqual(server_cipher_name, client_cipher_name)
2711
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002712 def test_get_cipher_version_before_connect(self):
2713 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002714 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2715 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002716 """
2717 ctx = Context(TLSv1_METHOD)
2718 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002719 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002720
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002721 def test_get_cipher_version(self):
2722 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002723 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2724 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002725 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002726 server, client = self._loopback()
2727 server_cipher_version, client_cipher_version = \
2728 server.get_cipher_version(), client.get_cipher_version()
2729
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002730 self.assertIsInstance(server_cipher_version, text_type)
2731 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002732
2733 self.assertEqual(server_cipher_version, client_cipher_version)
2734
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002735 def test_get_cipher_bits_before_connect(self):
2736 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002737 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2738 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002739 """
2740 ctx = Context(TLSv1_METHOD)
2741 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002742 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002743
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002744 def test_get_cipher_bits(self):
2745 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002746 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2747 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002748 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002749 server, client = self._loopback()
2750 server_cipher_bits, client_cipher_bits = \
2751 server.get_cipher_bits(), client.get_cipher_bits()
2752
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002753 self.assertIsInstance(server_cipher_bits, int)
2754 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002755
2756 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002757
Jim Shaverabff1882015-05-27 09:15:55 -04002758 def test_get_protocol_version_name(self):
2759 """
2760 :py:obj:`Connection.get_protocol_version_name()` returns a string
2761 giving the protocol version of the current connection.
2762 """
2763 server, client = self._loopback()
2764 client_protocol_version_name = client.get_protocol_version_name()
2765 server_protocol_version_name = server.get_protocol_version_name()
2766
Jim Shaver58d25732015-05-28 11:52:32 -04002767 self.assertIsInstance(server_protocol_version_name, text_type)
2768 self.assertIsInstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002769
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002770 self.assertEqual(
2771 server_protocol_version_name, client_protocol_version_name
2772 )
Jim Shaverabff1882015-05-27 09:15:55 -04002773
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002774 def test_get_protocol_version(self):
2775 """
Alex Gaynor43307782015-09-04 09:05:45 -04002776 :py:obj:`Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002777 giving the protocol version of the current connection.
2778 """
2779 server, client = self._loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002780 client_protocol_version = client.get_protocol_version()
2781 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002782
Jim Shaverabff1882015-05-27 09:15:55 -04002783 self.assertIsInstance(server_protocol_version, int)
2784 self.assertIsInstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002785
2786 self.assertEqual(server_protocol_version, client_protocol_version)
2787
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002788
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002789class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002790 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002791 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002792 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002793 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002794 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002795 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if
2796 called with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002797 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002798 connection = Connection(Context(TLSv1_METHOD), None)
2799 self.assertRaises(TypeError, connection.get_cipher_list, None)
2800
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002801 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002802 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002803 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2804 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002805 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002806 connection = Connection(Context(TLSv1_METHOD), None)
2807 ciphers = connection.get_cipher_list()
2808 self.assertTrue(isinstance(ciphers, list))
2809 for cipher in ciphers:
2810 self.assertTrue(isinstance(cipher, str))
2811
2812
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002813class ConnectionSendTests(TestCase, _LoopbackMixin):
2814 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002815 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002816 """
2817 def test_wrong_args(self):
2818 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002819 When called with arguments other than string argument for its first
2820 parameter or more than two arguments, :py:obj:`Connection.send` raises
2821 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002822 """
2823 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002824 self.assertRaises(TypeError, connection.send)
2825 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002826 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002827
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002828 def test_short_bytes(self):
2829 """
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002830 When passed a short byte string, :py:obj:`Connection.send` transmits
2831 all of it and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002832 """
2833 server, client = self._loopback()
2834 count = server.send(b('xy'))
2835 self.assertEquals(count, 2)
2836 self.assertEquals(client.recv(2), b('xy'))
2837
Abraham Martinef063482015-03-25 14:06:24 +00002838 def test_text(self):
2839 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002840 When passed a text, :py:obj:`Connection.send` transmits all of it and
2841 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002842 """
2843 server, client = self._loopback()
2844 with catch_warnings(record=True) as w:
2845 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002846 count = server.send(b"xy".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002847 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002848 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002849 WARNING_TYPE_EXPECTED
2850 ),
2851 str(w[-1].message)
2852 )
2853 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinef063482015-03-25 14:06:24 +00002854 self.assertEquals(count, 2)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002855 self.assertEquals(client.recv(2), b"xy")
Abraham Martinef063482015-03-25 14:06:24 +00002856
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002857 @skip_if_py26
2858 def test_short_memoryview(self):
2859 """
2860 When passed a memoryview onto a small number of bytes,
2861 :py:obj:`Connection.send` transmits all of them and returns the number
2862 of bytes sent.
2863 """
2864 server, client = self._loopback()
2865 count = server.send(memoryview(b('xy')))
2866 self.assertEquals(count, 2)
2867 self.assertEquals(client.recv(2), b('xy'))
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002868
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02002869 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002870 def test_short_buffer(self):
2871 """
2872 When passed a buffer containing a small number of bytes,
2873 :py:obj:`Connection.send` transmits all of them and returns the number
2874 of bytes sent.
2875 """
2876 server, client = self._loopback()
2877 count = server.send(buffer(b('xy')))
2878 self.assertEquals(count, 2)
2879 self.assertEquals(client.recv(2), b('xy'))
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002880
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002881
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002882def _make_memoryview(size):
2883 """
2884 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2885 size.
2886 """
2887 return memoryview(bytearray(size))
2888
2889
Cory Benfield62d10332014-06-15 10:03:41 +01002890class ConnectionRecvIntoTests(TestCase, _LoopbackMixin):
2891 """
2892 Tests for :py:obj:`Connection.recv_into`
2893 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002894 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002895 """
2896 Assert that when the given buffer is passed to
2897 ``Connection.recv_into``, whatever bytes are available to be received
2898 that fit into that buffer are written into that buffer.
2899 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002900 output_buffer = factory(5)
2901
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002902 server, client = self._loopback()
2903 server.send(b('xy'))
2904
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002905 self.assertEqual(client.recv_into(output_buffer), 2)
2906 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002907
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002908 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002909 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002910 :py:obj:`Connection.recv_into` can be passed a ``bytearray`` instance
2911 and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002912 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002913 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002914
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002915 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002916 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002917 Assert that when the given buffer is passed to ``Connection.recv_into``
2918 along with a value for ``nbytes`` that is less than the size of that
2919 buffer, only ``nbytes`` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002920 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002921 output_buffer = factory(10)
2922
Cory Benfield62d10332014-06-15 10:03:41 +01002923 server, client = self._loopback()
2924 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002925
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002926 self.assertEqual(client.recv_into(output_buffer, 5), 5)
2927 self.assertEqual(
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002928 output_buffer, bytearray(b('abcde\x00\x00\x00\x00\x00'))
2929 )
2930
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002931 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002932 """
2933 When called with a ``bytearray`` instance,
2934 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter and
2935 doesn't copy in more than that number of bytes.
2936 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002937 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002938
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002939 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002940 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002941 Assert that if there are more bytes available to be read from the
2942 receive buffer than would fit into the buffer passed to
2943 :py:obj:`Connection.recv_into`, only as many as fit are written into
2944 it.
Cory Benfield62d10332014-06-15 10:03:41 +01002945 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002946 output_buffer = factory(5)
2947
Cory Benfield62d10332014-06-15 10:03:41 +01002948 server, client = self._loopback()
2949 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002950
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002951 self.assertEqual(client.recv_into(output_buffer), 5)
2952 self.assertEqual(output_buffer, bytearray(b('abcde')))
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002953 rest = client.recv(5)
2954 self.assertEqual(b('fghij'), rest)
2955
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002956 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002957 """
2958 When called with a ``bytearray`` instance,
2959 :py:obj:`Connection.recv_into` respects the size of the array and
2960 doesn't write more bytes into it than will fit.
2961 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002962 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002963
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002964 def _really_doesnt_overfill_test(self, factory):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002965 """
2966 Assert that if the value given by ``nbytes`` is greater than the actual
2967 size of the output buffer passed to :py:obj:`Connection.recv_into`, the
2968 behavior is as if no value was given for ``nbytes`` at all.
2969 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002970 output_buffer = factory(5)
2971
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002972 server, client = self._loopback()
2973 server.send(b('abcdefghij'))
2974
2975 self.assertEqual(client.recv_into(output_buffer, 50), 5)
2976 self.assertEqual(output_buffer, bytearray(b('abcde')))
2977 rest = client.recv(5)
2978 self.assertEqual(b('fghij'), rest)
2979
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002980 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002981 """
2982 When called with a ``bytearray`` instance and an ``nbytes`` value that
2983 is too large, :py:obj:`Connection.recv_into` respects the size of the
2984 array and not the ``nbytes`` value and doesn't write more bytes into
2985 the buffer than will fit.
2986 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002987 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002988
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002989 def test_peek(self):
2990
2991 server, client = self._loopback()
2992 server.send(b('xy'))
2993
2994 for _ in range(2):
2995 output_buffer = bytearray(5)
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002996 self.assertEqual(
2997 client.recv_into(output_buffer, flags=MSG_PEEK), 2)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002998 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
2999
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003000 @skip_if_py26
3001 def test_memoryview_no_length(self):
3002 """
3003 :py:obj:`Connection.recv_into` can be passed a ``memoryview``
3004 instance and data in the receive buffer is written to it.
3005 """
3006 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003007
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003008 @skip_if_py26
3009 def test_memoryview_respects_length(self):
3010 """
3011 When called with a ``memoryview`` instance,
3012 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter
3013 and doesn't copy more than that number of bytes in.
3014 """
3015 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003016
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003017 @skip_if_py26
3018 def test_memoryview_doesnt_overfill(self):
3019 """
3020 When called with a ``memoryview`` instance,
3021 :py:obj:`Connection.recv_into` respects the size of the array and
3022 doesn't write more bytes into it than will fit.
3023 """
3024 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003025
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003026 @skip_if_py26
3027 def test_memoryview_really_doesnt_overfill(self):
3028 """
3029 When called with a ``memoryview`` instance and an ``nbytes`` value
3030 that is too large, :py:obj:`Connection.recv_into` respects the size
3031 of the array and not the ``nbytes`` value and doesn't write more
3032 bytes into the buffer than will fit.
3033 """
3034 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003035
Cory Benfield62d10332014-06-15 10:03:41 +01003036
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003037class ConnectionSendallTests(TestCase, _LoopbackMixin):
3038 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003039 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003040 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003041 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003042 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003043 When called with arguments other than a string argument for its first
3044 parameter or with more than two arguments, :py:obj:`Connection.sendall`
3045 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003046 """
3047 connection = Connection(Context(TLSv1_METHOD), None)
3048 self.assertRaises(TypeError, connection.sendall)
3049 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003050 self.assertRaises(
3051 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003052
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003053 def test_short(self):
3054 """
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003055 :py:obj:`Connection.sendall` transmits all of the bytes in the string
3056 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003057 """
3058 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04003059 server.sendall(b('x'))
3060 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003061
Abraham Martinef063482015-03-25 14:06:24 +00003062 def test_text(self):
3063 """
Jean-Paul Calderone93477422015-04-13 20:38:57 -04003064 :py:obj:`Connection.sendall` transmits all the content in the string
3065 passed to it raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003066 """
3067 server, client = self._loopback()
3068 with catch_warnings(record=True) as w:
3069 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003070 server.sendall(b"x".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003071 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003072 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003073 WARNING_TYPE_EXPECTED
3074 ),
3075 str(w[-1].message)
3076 )
3077 self.assertIs(w[-1].category, DeprecationWarning)
3078 self.assertEquals(client.recv(1), b"x")
Abraham Martinef063482015-03-25 14:06:24 +00003079
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003080 @skip_if_py26
3081 def test_short_memoryview(self):
3082 """
3083 When passed a memoryview onto a small number of bytes,
3084 :py:obj:`Connection.sendall` transmits all of them.
3085 """
3086 server, client = self._loopback()
3087 server.sendall(memoryview(b('x')))
3088 self.assertEquals(client.recv(1), b('x'))
Abraham Martinef063482015-03-25 14:06:24 +00003089
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003090 @skip_if_py3
3091 def test_short_buffers(self):
3092 """
3093 When passed a buffer containing a small number of bytes,
3094 :py:obj:`Connection.sendall` transmits all of them.
3095 """
3096 server, client = self._loopback()
3097 server.sendall(buffer(b('x')))
3098 self.assertEquals(client.recv(1), b('x'))
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003099
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003100 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003101 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003102 :py:obj:`Connection.sendall` transmits all of the bytes in the string
3103 passed to it even if this requires multiple calls of an underlying
3104 write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003105 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003106 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003107 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003108 # On Windows, after 32k of bytes the write will block (forever
3109 # - because no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04003110 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003111 server.sendall(message)
3112 accum = []
3113 received = 0
3114 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003115 data = client.recv(1024)
3116 accum.append(data)
3117 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04003118 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003119
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003120 def test_closed(self):
3121 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003122 If the underlying socket is closed, :py:obj:`Connection.sendall`
3123 propagates the write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003124 """
3125 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003126 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003127 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003128 if platform == "win32":
3129 self.assertEqual(exc.args[0], ESHUTDOWN)
3130 else:
3131 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003132
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003133
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003134class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
3135 """
3136 Tests for SSL renegotiation APIs.
3137 """
3138 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003139 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003140 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called
3141 with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003142 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003143 connection = Connection(Context(TLSv1_METHOD), None)
3144 self.assertRaises(TypeError, connection.renegotiate, None)
3145
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003146 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003147 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003148 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if
3149 called with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003150 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003151 connection = Connection(Context(TLSv1_METHOD), None)
3152 self.assertRaises(TypeError, connection.total_renegotiations, None)
3153
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003154 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003155 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003156 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before
3157 any renegotiations have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003158 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003159 connection = Connection(Context(TLSv1_METHOD), None)
3160 self.assertEquals(connection.total_renegotiations(), 0)
3161
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003162# def test_renegotiate(self):
3163# """
3164# """
3165# server, client = self._loopback()
3166
3167# server.send("hello world")
3168# self.assertEquals(client.recv(len("hello world")), "hello world")
3169
3170# self.assertEquals(server.total_renegotiations(), 0)
3171# self.assertTrue(server.renegotiate())
3172
3173# server.setblocking(False)
3174# client.setblocking(False)
3175# while server.renegotiate_pending():
3176# client.do_handshake()
3177# server.do_handshake()
3178
3179# self.assertEquals(server.total_renegotiations(), 1)
3180
3181
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003182class ErrorTests(TestCase):
3183 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003184 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003185 """
3186 def test_type(self):
3187 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003188 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003189 """
3190 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05003191 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05003192
3193
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003194class ConstantsTests(TestCase):
3195 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003196 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003197
3198 These are values defined by OpenSSL intended only to be used as flags to
3199 OpenSSL APIs. The only assertions it seems can be made about them is
3200 their values.
3201 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003202 @pytest.mark.skipif(
3203 OP_NO_QUERY_MTU is None,
3204 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
3205 )
3206 def test_op_no_query_mtu(self):
3207 """
3208 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3209 of :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
3210 """
3211 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003212
Hynek Schlawack35618382015-09-05 21:54:25 +02003213 @pytest.mark.skipif(
3214 OP_COOKIE_EXCHANGE is None,
3215 reason="OP_COOKIE_EXCHANGE unavailable - "
3216 "OpenSSL version may be too old"
3217 )
3218 def test_op_cookie_exchange(self):
3219 """
3220 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3221 value of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by
3222 :file:`openssl/ssl.h`.
3223 """
3224 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003225
Hynek Schlawack35618382015-09-05 21:54:25 +02003226 @pytest.mark.skipif(
3227 OP_NO_TICKET is None,
3228 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old"
3229 )
3230 def test_op_no_ticket(self):
3231 """
3232 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3233 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
3234 """
3235 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003236
Hynek Schlawack35618382015-09-05 21:54:25 +02003237 @pytest.mark.skipif(
3238 OP_NO_COMPRESSION is None,
3239 reason="OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3240 )
3241 def test_op_no_compression(self):
3242 """
3243 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3244 value of :py:const:`SSL_OP_NO_COMPRESSION` defined by
3245 :file:`openssl/ssl.h`.
3246 """
3247 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003248
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003249 def test_sess_cache_off(self):
3250 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003251 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3252 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003253 """
3254 self.assertEqual(0x0, SESS_CACHE_OFF)
3255
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003256 def test_sess_cache_client(self):
3257 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003258 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3259 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003260 """
3261 self.assertEqual(0x1, SESS_CACHE_CLIENT)
3262
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003263 def test_sess_cache_server(self):
3264 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003265 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3266 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003267 """
3268 self.assertEqual(0x2, SESS_CACHE_SERVER)
3269
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003270 def test_sess_cache_both(self):
3271 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003272 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3273 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003274 """
3275 self.assertEqual(0x3, SESS_CACHE_BOTH)
3276
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003277 def test_sess_cache_no_auto_clear(self):
3278 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003279 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3280 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3281 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003282 """
3283 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
3284
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003285 def test_sess_cache_no_internal_lookup(self):
3286 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003287 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3288 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3289 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003290 """
3291 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
3292
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003293 def test_sess_cache_no_internal_store(self):
3294 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003295 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3296 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3297 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003298 """
3299 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
3300
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003301 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 Calderonebf37f0f2010-07-31 14:56:20 -04003310class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05003311 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003312 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003313 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003314 def _server(self, sock):
3315 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003316 Create a new server-side SSL :py:obj:`Connection` object wrapped around
3317 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003318 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003319 # Create the server side Connection. This is mostly setup boilerplate
3320 # - use TLSv1, use a particular certificate, etc.
3321 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003322 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003323 server_ctx.set_verify(
3324 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3325 verify_cb
3326 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003327 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003328 server_ctx.use_privatekey(
3329 load_privatekey(FILETYPE_PEM, server_key_pem))
3330 server_ctx.use_certificate(
3331 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003332 server_ctx.check_privatekey()
3333 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003334 # Here the Connection is actually created. If None is passed as the
3335 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003336 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003337 server_conn.set_accept_state()
3338 return server_conn
3339
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003340 def _client(self, sock):
3341 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003342 Create a new client-side SSL :py:obj:`Connection` object wrapped around
3343 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003344 """
3345 # Now create the client side Connection. Similar boilerplate to the
3346 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003347 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003348 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003349 client_ctx.set_verify(
3350 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3351 verify_cb
3352 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003353 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003354 client_ctx.use_privatekey(
3355 load_privatekey(FILETYPE_PEM, client_key_pem))
3356 client_ctx.use_certificate(
3357 load_certificate(FILETYPE_PEM, client_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003358 client_ctx.check_privatekey()
3359 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003360 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003361 client_conn.set_connect_state()
3362 return client_conn
3363
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003364 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003365 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003366 Two :py:obj:`Connection`s which use memory BIOs can be manually
3367 connected by reading from the output of each and writing those bytes to
3368 the input of the other and in this way establish a connection and
3369 exchange application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003370 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003371 server_conn = self._server(None)
3372 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003373
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003374 # There should be no key or nonces yet.
3375 self.assertIdentical(server_conn.master_key(), None)
3376 self.assertIdentical(server_conn.client_random(), None)
3377 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003378
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003379 # First, the handshake needs to happen. We'll deliver bytes back and
3380 # forth between the client and server until neither of them feels like
3381 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003382 self.assertIdentical(
3383 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003384
3385 # Now that the handshake is done, there should be a key and nonces.
3386 self.assertNotIdentical(server_conn.master_key(), None)
3387 self.assertNotIdentical(server_conn.client_random(), None)
3388 self.assertNotIdentical(server_conn.server_random(), None)
Hynek Schlawack35618382015-09-05 21:54:25 +02003389 self.assertEquals(
3390 server_conn.client_random(), client_conn.client_random())
3391 self.assertEquals(
3392 server_conn.server_random(), client_conn.server_random())
3393 self.assertNotEquals(
3394 server_conn.client_random(), server_conn.server_random())
3395 self.assertNotEquals(
3396 client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003397
3398 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003399 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05003400
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003401 server_conn.write(important_message)
3402 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003403 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003404 (client_conn, important_message))
3405
3406 client_conn.write(important_message[::-1])
3407 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003408 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003409 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003410
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003411 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003412 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003413 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003414
Hynek Schlawack35618382015-09-05 21:54:25 +02003415 This is primarily to rule out the memory BIO code as the source of any
3416 problems encountered while passing data over a :py:obj:`Connection` (if
3417 this test fails, there must be a problem outside the memory BIO code,
3418 as no memory BIO is involved here). Even though this isn't a memory
3419 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003420 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04003421 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003422
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003423 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05003424 client_conn.send(important_message)
3425 msg = server_conn.recv(1024)
3426 self.assertEqual(msg, important_message)
3427
3428 # Again in the other direction, just for fun.
3429 important_message = important_message[::-1]
3430 server_conn.send(important_message)
3431 msg = client_conn.recv(1024)
3432 self.assertEqual(msg, important_message)
3433
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04003434 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003435 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003436 Test that :py:obj:`OpenSSL.SSL.bio_read` and
3437 :py:obj:`OpenSSL.SSL.bio_write` don't work on
3438 :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003439 """
3440 context = Context(SSLv3_METHOD)
3441 client = socket()
3442 clientSSL = Connection(context, client)
Alex Gaynor43307782015-09-04 09:05:45 -04003443 self.assertRaises(TypeError, clientSSL.bio_read, 100)
3444 self.assertRaises(TypeError, clientSSL.bio_write, "foo")
Alex Gaynor7e8b61e2015-09-04 13:13:05 -04003445 self.assertRaises(TypeError, clientSSL.bio_shutdown)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003446
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003447 def test_outgoingOverflow(self):
3448 """
3449 If more bytes than can be written to the memory BIO are passed to
Hynek Schlawack35618382015-09-05 21:54:25 +02003450 :py:obj:`Connection.send` at once, the number of bytes which were
3451 written is returned and that many bytes from the beginning of the input
3452 can be read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003453 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003454 server = self._server(None)
3455 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003456
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003457 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003458
3459 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003460 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003461 # Sanity check. We're trying to test what happens when the entire
3462 # input can't be sent. If the entire input was sent, this test is
3463 # meaningless.
3464 self.assertTrue(sent < size)
3465
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003466 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003467 self.assertIdentical(receiver, server)
3468
3469 # We can rely on all of these bytes being received at once because
3470 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
3471 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003472
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003473 def test_shutdown(self):
3474 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003475 :py:obj:`Connection.bio_shutdown` signals the end of the data stream
3476 from which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003477 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003478 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003479 server.bio_shutdown()
3480 e = self.assertRaises(Error, server.recv, 1024)
3481 # We don't want WantReadError or ZeroReturnError or anything - it's a
3482 # handshake failure.
3483 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003484
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003485 def test_unexpectedEndOfFile(self):
3486 """
3487 If the connection is lost before an orderly SSL shutdown occurs,
3488 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
3489 "Unexpected EOF".
3490 """
3491 server_conn, client_conn = self._loopback()
3492 client_conn.sock_shutdown(SHUT_RDWR)
3493 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
3494 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
3495
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003496 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003497 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003498 Verify the return value of the :py:obj:`get_client_ca_list` method for
3499 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003500
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003501 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003502 before the client and server are connected to each other. This
3503 function should specify a list of CAs for the server to send to the
3504 client and return that same list. The list will be used to verify
Hynek Schlawack35618382015-09-05 21:54:25 +02003505 that :py:obj:`get_client_ca_list` returns the proper value at
3506 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003507 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003508 server = self._server(None)
3509 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003510 self.assertEqual(client.get_client_ca_list(), [])
3511 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003512 ctx = server.get_context()
3513 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003514 self.assertEqual(client.get_client_ca_list(), [])
3515 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003516 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003517 self.assertEqual(client.get_client_ca_list(), expected)
3518 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003519
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003520 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003521 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003522 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if
3523 called with a non-list or a list that contains objects other than
3524 X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003525 """
3526 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003527 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
3528 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
3529 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003530
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003531 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003532 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003533 If passed an empty list, :py:obj:`Context.set_client_ca_list`
3534 configures the context to send no CA names to the client and, on both
3535 the server and client sides, :py:obj:`Connection.get_client_ca_list`
3536 returns an empty list after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003537 """
3538 def no_ca(ctx):
3539 ctx.set_client_ca_list([])
3540 return []
3541 self._check_client_ca_list(no_ca)
3542
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003543 def test_set_one_ca_list(self):
3544 """
3545 If passed a list containing a single X509Name,
Hynek Schlawack35618382015-09-05 21:54:25 +02003546 :py:obj:`Context.set_client_ca_list` configures the context to send
3547 that CA name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003548 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003549 X509Name after the connection is set up.
3550 """
3551 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3552 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003553
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003554 def single_ca(ctx):
3555 ctx.set_client_ca_list([cadesc])
3556 return [cadesc]
3557 self._check_client_ca_list(single_ca)
3558
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003559 def test_set_multiple_ca_list(self):
3560 """
3561 If passed a list containing multiple X509Name objects,
Hynek Schlawack35618382015-09-05 21:54:25 +02003562 :py:obj:`Context.set_client_ca_list` configures the context to send
3563 those CA names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003564 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003565 X509Names after the connection is set up.
3566 """
3567 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3568 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3569
3570 sedesc = secert.get_subject()
3571 cldesc = clcert.get_subject()
3572
3573 def multiple_ca(ctx):
3574 L = [sedesc, cldesc]
3575 ctx.set_client_ca_list(L)
3576 return L
3577 self._check_client_ca_list(multiple_ca)
3578
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003579 def test_reset_ca_list(self):
3580 """
3581 If called multiple times, only the X509Names passed to the final call
Hynek Schlawack35618382015-09-05 21:54:25 +02003582 of :py:obj:`Context.set_client_ca_list` are used to configure the CA
3583 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003584 """
3585 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3586 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3587 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3588
3589 cadesc = cacert.get_subject()
3590 sedesc = secert.get_subject()
3591 cldesc = clcert.get_subject()
3592
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003593 def changed_ca(ctx):
3594 ctx.set_client_ca_list([sedesc, cldesc])
3595 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003596 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003597 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003598
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003599 def test_mutated_ca_list(self):
3600 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003601 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003602 afterwards, this does not affect the list of CA names sent to the
3603 client.
3604 """
3605 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3606 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3607
3608 cadesc = cacert.get_subject()
3609 sedesc = secert.get_subject()
3610
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003611 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003612 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003613 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003614 L.append(sedesc)
3615 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003616 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003617
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003618 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003619 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003620 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called
3621 with a non-X509 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003622 """
3623 ctx = Context(TLSv1_METHOD)
3624 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003625 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003626 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003627 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003628
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003629 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003630 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003631 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09003632 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003633 """
3634 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3635 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003636
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003637 def single_ca(ctx):
3638 ctx.add_client_ca(cacert)
3639 return [cadesc]
3640 self._check_client_ca_list(single_ca)
3641
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003642 def test_multiple_add_client_ca(self):
3643 """
3644 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09003645 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003646 """
3647 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3648 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3649
3650 cadesc = cacert.get_subject()
3651 sedesc = secert.get_subject()
3652
3653 def multiple_ca(ctx):
3654 ctx.add_client_ca(cacert)
3655 ctx.add_client_ca(secert)
3656 return [cadesc, sedesc]
3657 self._check_client_ca_list(multiple_ca)
3658
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003659 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
Hynek Schlawack35618382015-09-05 21:54:25 +02003662 :py:obj:`Context.add_client_ca` results in using the CA names from the
3663 first 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 def test_set_after_add_client_ca(self):
3680 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003681 A call to :py:obj:`Context.set_client_ca_list` after a call to
Hynek Schlawack35618382015-09-05 21:54:25 +02003682 :py:obj:`Context.add_client_ca` replaces the CA name specified by the
3683 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003684 """
3685 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3686 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3687 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3688
3689 cadesc = cacert.get_subject()
3690 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003691
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003692 def set_replaces_add_ca(ctx):
3693 ctx.add_client_ca(clcert)
3694 ctx.set_client_ca_list([cadesc])
3695 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003696 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003697 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003698
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003699
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003700class ConnectionBIOTests(TestCase):
3701 """
3702 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3703 """
3704 def test_wantReadError(self):
3705 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003706 :py:obj:`Connection.bio_read` raises
3707 :py:obj:`OpenSSL.SSL.WantReadError` if there are no bytes available to
3708 be read from the BIO.
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003709 """
3710 ctx = Context(TLSv1_METHOD)
3711 conn = Connection(ctx, None)
3712 self.assertRaises(WantReadError, conn.bio_read, 1024)
3713
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003714 def test_buffer_size(self):
3715 """
3716 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3717 number of bytes to read and return.
3718 """
3719 ctx = Context(TLSv1_METHOD)
3720 conn = Connection(ctx, None)
3721 conn.set_connect_state()
3722 try:
3723 conn.do_handshake()
3724 except WantReadError:
3725 pass
3726 data = conn.bio_read(2)
3727 self.assertEqual(2, len(data))
3728
Hynek Schlawack35618382015-09-05 21:54:25 +02003729 @skip_if_py3
3730 def test_buffer_size_long(self):
3731 """
3732 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3733 :py:obj:`long` as well as :py:obj:`int`.
3734 """
3735 ctx = Context(TLSv1_METHOD)
3736 conn = Connection(ctx, None)
3737 conn.set_connect_state()
3738 try:
3739 conn.do_handshake()
3740 except WantReadError:
3741 pass
3742 data = conn.bio_read(long(2))
3743 self.assertEqual(2, len(data))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003744
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003745
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003746class InfoConstantTests(TestCase):
3747 """
3748 Tests for assorted constants exposed for use in info callbacks.
3749 """
3750 def test_integers(self):
3751 """
3752 All of the info constants are integers.
3753
3754 This is a very weak test. It would be nice to have one that actually
3755 verifies that as certain info events happen, the value passed to the
3756 info callback matches up with the constant exposed by OpenSSL.SSL.
3757 """
3758 for const in [
3759 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3760 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3761 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3762 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3763 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
Hynek Schlawack35618382015-09-05 21:54:25 +02003764 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE
3765 ]:
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003766 self.assertTrue(isinstance(const, int))
3767
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003768
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003769if __name__ == '__main__':
3770 main()