blob: c9f5251a8c8aca4f51707b38ebe7caa2d49e1dc7 [file] [log] [blame]
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05001# Copyright (C) Jean-Paul Calderone
2# See LICENSE for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04003
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04004"""
Jonathan Ballet648875f2011-07-16 14:14:58 +09005Unit tests for :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04006"""
7
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05008from gc import collect, get_referrers
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02009from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE, ESHUTDOWN
Jean-Paul Calderone516c12c2015-04-13 20:34:57 -040010from sys import platform, getfilesystemencoding
Maximilian Hils1d95dea2015-08-17 19:27:20 +020011from socket import MSG_PEEK, SHUT_RDWR, error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040012from os import makedirs
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040013from os.path import join
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -040014from unittest import main
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040015from weakref import ref
Abraham Martinef063482015-03-25 14:06:24 +000016from warnings import catch_warnings, simplefilter
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050017
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -040018from six import PY3, text_type, u
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050019
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040020from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080021from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040022from OpenSSL.crypto import dump_privatekey, load_privatekey
23from OpenSSL.crypto import dump_certificate, load_certificate
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040024from OpenSSL.crypto import get_elliptic_curves
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040025
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040026from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
27from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040028from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040029from OpenSSL.SSL import (
30 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
31 TLSv1_1_METHOD, TLSv1_2_METHOD)
32from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040033from OpenSSL.SSL import (
34 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040035
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040036from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050037 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
38 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
39 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
40
41from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070042 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050043from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070044 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040045
Cory Benfieldba1820d2015-04-13 17:39:12 -040046from OpenSSL._util import lib as _lib
47
Jean-Paul Calderone17eca482015-04-13 20:31:07 -040048from OpenSSL.test.util import WARNING_TYPE_EXPECTED, NON_ASCII, TestCase, b
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040049from OpenSSL.test.test_crypto import (
Jean-Paul Calderoneda6399a2015-04-13 20:52:29 -040050 cleartextCertificatePEM, cleartextPrivateKeyPEM,
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040051 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
52 root_cert_pem)
53
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050054try:
55 from OpenSSL.SSL import OP_NO_QUERY_MTU
56except ImportError:
57 OP_NO_QUERY_MTU = None
58try:
59 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
60except ImportError:
61 OP_COOKIE_EXCHANGE = None
62try:
63 from OpenSSL.SSL import OP_NO_TICKET
64except ImportError:
65 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040066
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040067try:
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -040068 from OpenSSL.SSL import OP_NO_COMPRESSION
69except ImportError:
70 OP_NO_COMPRESSION = None
71
72try:
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040073 from OpenSSL.SSL import MODE_RELEASE_BUFFERS
74except ImportError:
75 MODE_RELEASE_BUFFERS = None
76
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040077try:
78 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
79except ImportError:
80 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
81
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040082from OpenSSL.SSL import (
83 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
84 SSL_ST_OK, SSL_ST_RENEGOTIATE,
85 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
86 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
87 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
88 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040089
Hynek Schlawackde00dd52015-09-05 19:09:26 +020090
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040091# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
92# to use)
93dhparam = """\
94-----BEGIN DH PARAMETERS-----
95MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
96-----END DH PARAMETERS-----
97"""
98
99
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400100def join_bytes_or_unicode(prefix, suffix):
101 """
102 Join two path components of either ``bytes`` or ``unicode``.
103
104 The return type is the same as the type of ``prefix``.
105 """
106 # If the types are the same, nothing special is necessary.
107 if type(prefix) == type(suffix):
108 return join(prefix, suffix)
109
110 # Otherwise, coerce suffix to the type of prefix.
111 if isinstance(prefix, text_type):
112 return join(prefix, suffix.decode(getfilesystemencoding()))
113 else:
114 return join(prefix, suffix.encode(getfilesystemencoding()))
115
116
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400117def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400118 return ok
119
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400120
Rick Deanb1ccd562009-07-09 23:52:39 -0500121def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400122 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400123 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400124 """
125 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500126 port = socket()
127 port.bind(('', 0))
128 port.listen(1)
129 client = socket()
130 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400131 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400132 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500133 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500134
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400135 # Let's pass some unencrypted data to make sure our socket connection is
136 # fine. Just one byte, so we don't have to worry about buffers getting
137 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400138 server.send(b("x"))
139 assert client.recv(1024) == b("x")
140 client.send(b("y"))
141 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500142
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400143 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400144 server.setblocking(False)
145 client.setblocking(False)
Jim Shaver46f28912015-05-29 19:32:16 -0400146
Rick Deanb1ccd562009-07-09 23:52:39 -0500147 return (server, client)
148
149
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400150def handshake(client, server):
151 conns = [client, server]
152 while conns:
153 for conn in conns:
154 try:
155 conn.do_handshake()
156 except WantReadError:
157 pass
158 else:
159 conns.remove(conn)
160
161
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400162def _create_certificate_chain():
163 """
164 Construct and return a chain of certificates.
165
166 1. A new self-signed certificate authority certificate (cacert)
167 2. A new intermediate certificate signed by cacert (icert)
168 3. A new server certificate signed by icert (scert)
169 """
170 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
171
172 # Step 1
173 cakey = PKey()
174 cakey.generate_key(TYPE_RSA, 512)
175 cacert = X509()
176 cacert.get_subject().commonName = "Authority Certificate"
177 cacert.set_issuer(cacert.get_subject())
178 cacert.set_pubkey(cakey)
179 cacert.set_notBefore(b("20000101000000Z"))
180 cacert.set_notAfter(b("20200101000000Z"))
181 cacert.add_extensions([caext])
182 cacert.set_serial_number(0)
183 cacert.sign(cakey, "sha1")
184
185 # Step 2
186 ikey = PKey()
187 ikey.generate_key(TYPE_RSA, 512)
188 icert = X509()
189 icert.get_subject().commonName = "Intermediate Certificate"
190 icert.set_issuer(cacert.get_subject())
191 icert.set_pubkey(ikey)
192 icert.set_notBefore(b("20000101000000Z"))
193 icert.set_notAfter(b("20200101000000Z"))
194 icert.add_extensions([caext])
195 icert.set_serial_number(0)
196 icert.sign(cakey, "sha1")
197
198 # Step 3
199 skey = PKey()
200 skey.generate_key(TYPE_RSA, 512)
201 scert = X509()
202 scert.get_subject().commonName = "Server Certificate"
203 scert.set_issuer(icert.get_subject())
204 scert.set_pubkey(skey)
205 scert.set_notBefore(b("20000101000000Z"))
206 scert.set_notAfter(b("20200101000000Z"))
207 scert.add_extensions([
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200208 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400209 scert.set_serial_number(0)
210 scert.sign(ikey, "sha1")
211
212 return [(cakey, cacert), (ikey, icert), (skey, scert)]
213
214
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400215class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400216 """
217 Helper mixin which defines methods for creating a connected socket pair and
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200218 for forcing two connected SSL sockets to talk to each other via memory
219 BIOs.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400220 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500221 def _loopbackClientFactory(self, socket):
222 client = Connection(Context(TLSv1_METHOD), socket)
223 client.set_connect_state()
224 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400225
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500226 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400227 ctx = Context(TLSv1_METHOD)
228 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
229 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500230 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400231 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500232 return server
233
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500234 def _loopback(self, serverFactory=None, clientFactory=None):
235 if serverFactory is None:
236 serverFactory = self._loopbackServerFactory
237 if clientFactory is None:
238 clientFactory = self._loopbackClientFactory
239
240 (server, client) = socket_pair()
241 server = serverFactory(server)
242 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400243
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400244 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400245
246 server.setblocking(True)
247 client.setblocking(True)
248 return server, client
249
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400250 def _interactInMemory(self, client_conn, server_conn):
251 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900252 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400253 objects. Copy bytes back and forth between their send/receive buffers
254 for as long as there is anything to copy. When there is nothing more
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200255 to copy, return :py:obj:`None`. If one of them actually manages to
256 deliver some application bytes, return a two-tuple of the connection
257 from which the bytes were read and the bytes themselves.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400258 """
259 wrote = True
260 while wrote:
261 # Loop until neither side has anything to say
262 wrote = False
263
264 # Copy stuff from each side's send buffer to the other side's
265 # receive buffer.
266 for (read, write) in [(client_conn, server_conn),
267 (server_conn, client_conn)]:
268
269 # Give the side a chance to generate some more bytes, or
270 # succeed.
271 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400272 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400273 except WantReadError:
274 # It didn't succeed, so we'll hope it generated some
275 # output.
276 pass
277 else:
278 # It did succeed, so we'll stop now and let the caller deal
279 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400280 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400281
282 while True:
283 # Keep copying as long as there's more stuff there.
284 try:
285 dirty = read.bio_read(4096)
286 except WantReadError:
287 # Okay, nothing more waiting to be sent. Stop
288 # processing this send buffer.
289 break
290 else:
291 # Keep track of the fact that someone generated some
292 # output.
293 wrote = True
294 write.bio_write(dirty)
295
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400296 def _handshakeInMemory(self, client_conn, server_conn):
Jean-Paul Calderoneb2b40782014-05-06 08:47:40 -0400297 """
298 Perform the TLS handshake between two :py:class:`Connection` instances
299 connected to each other via memory BIOs.
300 """
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400301 client_conn.set_connect_state()
302 server_conn.set_accept_state()
303
304 for conn in [client_conn, server_conn]:
305 try:
306 conn.do_handshake()
307 except WantReadError:
308 pass
309
310 self._interactInMemory(client_conn, server_conn)
311
312
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400313class VersionTests(TestCase):
314 """
315 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900316 :py:obj:`OpenSSL.SSL.SSLeay_version` and
317 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400318 """
319 def test_OPENSSL_VERSION_NUMBER(self):
320 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900321 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400322 byte and the patch, fix, minor, and major versions in the
323 nibbles above that.
324 """
325 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
326
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400327 def test_SSLeay_version(self):
328 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900329 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400330 one of a number of version strings based on that indicator.
331 """
332 versions = {}
333 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
334 SSLEAY_PLATFORM, SSLEAY_DIR]:
335 version = SSLeay_version(t)
336 versions[version] = t
337 self.assertTrue(isinstance(version, bytes))
338 self.assertEqual(len(versions), 5)
339
340
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400341class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400342 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900343 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400344 """
345 def test_method(self):
346 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200347 :py:obj:`Context` can be instantiated with one of
348 :py:obj:`SSLv2_METHOD`, :py:obj:`SSLv3_METHOD`,
349 :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400350 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400351 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400352 methods = [
353 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
354 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400355 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400356
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400357 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
358 for meth in maybe:
359 try:
360 Context(meth)
361 except (Error, ValueError):
362 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
363 # don't. Difficult to say in advance.
364 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400365
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400366 self.assertRaises(TypeError, Context, "")
367 self.assertRaises(ValueError, Context, 10)
368
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500369 if not PY3:
370 def test_method_long(self):
371 """
372 On Python 2 :py:class:`Context` accepts values of type
373 :py:obj:`long` as well as :py:obj:`int`.
374 """
375 Context(long(TLSv1_METHOD))
376
Rick Deane15b1472009-07-09 15:53:42 -0500377 def test_type(self):
378 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200379 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type
380 object and can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500381 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400382 self.assertIdentical(Context, ContextType)
383 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500384
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400385 def test_use_privatekey(self):
386 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200387 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey`
388 instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400389 """
390 key = PKey()
391 key.generate_key(TYPE_RSA, 128)
392 ctx = Context(TLSv1_METHOD)
393 ctx.use_privatekey(key)
394 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400395
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800396 def test_use_privatekey_file_missing(self):
397 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200398 :py:obj:`Context.use_privatekey_file` raises
399 :py:obj:`OpenSSL.SSL.Error` when passed the name of a file which does
400 not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800401 """
402 ctx = Context(TLSv1_METHOD)
403 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
404
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400405 def _use_privatekey_file_test(self, pemfile, filetype):
406 """
407 Verify that calling ``Context.use_privatekey_file`` with the given
408 arguments does not raise an exception.
409 """
410 key = PKey()
411 key.generate_key(TYPE_RSA, 128)
412
413 with open(pemfile, "wt") as pem:
414 pem.write(
415 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
416 )
417
418 ctx = Context(TLSv1_METHOD)
419 ctx.use_privatekey_file(pemfile, filetype)
420
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400421 def test_use_privatekey_file_bytes(self):
422 """
423 A private key can be specified from a file by passing a ``bytes``
424 instance giving the file name to ``Context.use_privatekey_file``.
425 """
426 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400427 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400428 FILETYPE_PEM,
429 )
430
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400431 def test_use_privatekey_file_unicode(self):
432 """
433 A private key can be specified from a file by passing a ``unicode``
434 instance giving the file name to ``Context.use_privatekey_file``.
435 """
436 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400437 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400438 FILETYPE_PEM,
439 )
440
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500441 if not PY3:
442 def test_use_privatekey_file_long(self):
443 """
444 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
445 filetype of type :py:obj:`long` as well as :py:obj:`int`.
446 """
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400447 self._use_privatekey_file_test(self.mktemp(), long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500448
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800449 def test_use_certificate_wrong_args(self):
450 """
451 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200452 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as
453 an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800454 """
455 ctx = Context(TLSv1_METHOD)
456 self.assertRaises(TypeError, ctx.use_certificate)
457 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200458 self.assertRaises(
459 TypeError, ctx.use_certificate, X509(), "hello, world"
460 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800461
462 def test_use_certificate_uninitialized(self):
463 """
464 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
465 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
466 initialized (ie, which does not actually have any certificate data).
467 """
468 ctx = Context(TLSv1_METHOD)
469 self.assertRaises(Error, ctx.use_certificate, X509())
470
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800471 def test_use_certificate(self):
472 """
473 :py:obj:`Context.use_certificate` sets the certificate which will be
474 used to identify connections created using the context.
475 """
476 # TODO
477 # Hard to assert anything. But we could set a privatekey then ask
478 # OpenSSL if the cert and key agree using check_privatekey. Then as
479 # long as check_privatekey works right we're good...
480 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200481 ctx.use_certificate(
482 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
483 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800484
485 def test_use_certificate_file_wrong_args(self):
486 """
487 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
488 called with zero arguments or more than two arguments, or if the first
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200489 argument is not a byte string or the second argumnent is not an
490 integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800491 """
492 ctx = Context(TLSv1_METHOD)
493 self.assertRaises(TypeError, ctx.use_certificate_file)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200494 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile",
495 object())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800496 self.assertRaises(
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200497 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM,
498 object())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800499 self.assertRaises(
500 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
501 self.assertRaises(
502 TypeError, ctx.use_certificate_file, b"somefile", object())
503
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800504 def test_use_certificate_file_missing(self):
505 """
506 :py:obj:`Context.use_certificate_file` raises
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200507 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does
508 not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800509 """
510 ctx = Context(TLSv1_METHOD)
511 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
512
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400513 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800514 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400515 Verify that calling ``Context.use_certificate_file`` with the given
516 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800517 """
518 # TODO
519 # Hard to assert anything. But we could set a privatekey then ask
520 # OpenSSL if the cert and key agree using check_privatekey. Then as
521 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400522 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800523 pem_file.write(cleartextCertificatePEM)
524
525 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400526 ctx.use_certificate_file(certificate_file)
527
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400528 def test_use_certificate_file_bytes(self):
529 """
530 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
531 ``bytes`` filename) which will be used to identify connections created
532 using the context.
533 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400534 filename = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400535 self._use_certificate_file_test(filename)
536
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400537 def test_use_certificate_file_unicode(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().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400544 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800545
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500546 if not PY3:
547 def test_use_certificate_file_long(self):
548 """
549 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
550 filetype of type :py:obj:`long` as well as :py:obj:`int`.
551 """
552 pem_filename = self.mktemp()
553 with open(pem_filename, "wb") as pem_file:
554 pem_file.write(cleartextCertificatePEM)
555
556 ctx = Context(TLSv1_METHOD)
557 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
558
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500559 def test_check_privatekey_valid(self):
560 """
561 :py:obj:`Context.check_privatekey` returns :py:obj:`None` if the
562 :py:obj:`Context` instance has been configured to use a matched key and
563 certificate pair.
564 """
565 key = load_privatekey(FILETYPE_PEM, client_key_pem)
566 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
567 context = Context(TLSv1_METHOD)
568 context.use_privatekey(key)
569 context.use_certificate(cert)
570 self.assertIs(None, context.check_privatekey())
571
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500572 def test_check_privatekey_invalid(self):
573 """
574 :py:obj:`Context.check_privatekey` raises :py:obj:`Error` if the
575 :py:obj:`Context` instance has been configured to use a key and
576 certificate pair which don't relate to each other.
577 """
578 key = load_privatekey(FILETYPE_PEM, client_key_pem)
579 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
580 context = Context(TLSv1_METHOD)
581 context.use_privatekey(key)
582 context.use_certificate(cert)
583 self.assertRaises(Error, context.check_privatekey)
584
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500585 def test_check_privatekey_wrong_args(self):
586 """
587 :py:obj:`Context.check_privatekey` raises :py:obj:`TypeError` if called
588 with other than no arguments.
589 """
590 context = Context(TLSv1_METHOD)
591 self.assertRaises(TypeError, context.check_privatekey, object())
592
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400593 def test_set_app_data_wrong_args(self):
594 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200595 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called
596 with other than one argument.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400597 """
598 context = Context(TLSv1_METHOD)
599 self.assertRaises(TypeError, context.set_app_data)
600 self.assertRaises(TypeError, context.set_app_data, None, None)
601
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400602 def test_get_app_data_wrong_args(self):
603 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200604 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called
605 with any arguments.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400606 """
607 context = Context(TLSv1_METHOD)
608 self.assertRaises(TypeError, context.get_app_data, None)
609
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400610 def test_app_data(self):
611 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200612 :py:obj:`Context.set_app_data` stores an object for later retrieval
613 using :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400614 """
615 app_data = object()
616 context = Context(TLSv1_METHOD)
617 context.set_app_data(app_data)
618 self.assertIdentical(context.get_app_data(), app_data)
619
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400620 def test_set_options_wrong_args(self):
621 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200622 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with
623 the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400624 """
625 context = Context(TLSv1_METHOD)
626 self.assertRaises(TypeError, context.set_options)
627 self.assertRaises(TypeError, context.set_options, None)
628 self.assertRaises(TypeError, context.set_options, 1, None)
629
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500630 def test_set_options(self):
631 """
632 :py:obj:`Context.set_options` returns the new options value.
633 """
634 context = Context(TLSv1_METHOD)
635 options = context.set_options(OP_NO_SSLv2)
636 self.assertTrue(OP_NO_SSLv2 & options)
637
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500638 if not PY3:
639 def test_set_options_long(self):
640 """
641 On Python 2 :py:obj:`Context.set_options` accepts values of type
642 :py:obj:`long` as well as :py:obj:`int`.
643 """
644 context = Context(TLSv1_METHOD)
645 options = context.set_options(long(OP_NO_SSLv2))
646 self.assertTrue(OP_NO_SSLv2 & options)
647
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300648 def test_set_mode_wrong_args(self):
649 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200650 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with
651 the wrong number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300652 """
653 context = Context(TLSv1_METHOD)
654 self.assertRaises(TypeError, context.set_mode)
655 self.assertRaises(TypeError, context.set_mode, None)
656 self.assertRaises(TypeError, context.set_mode, 1, None)
657
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400658 if MODE_RELEASE_BUFFERS is not None:
659 def test_set_mode(self):
660 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200661 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the
662 newly set mode.
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400663 """
664 context = Context(TLSv1_METHOD)
665 self.assertTrue(
666 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500667
668 if not PY3:
669 def test_set_mode_long(self):
670 """
671 On Python 2 :py:obj:`Context.set_mode` accepts values of type
672 :py:obj:`long` as well as :py:obj:`int`.
673 """
674 context = Context(TLSv1_METHOD)
675 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
676 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400677 else:
678 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
679
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400680 def test_set_timeout_wrong_args(self):
681 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200682 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with
683 the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400684 """
685 context = Context(TLSv1_METHOD)
686 self.assertRaises(TypeError, context.set_timeout)
687 self.assertRaises(TypeError, context.set_timeout, None)
688 self.assertRaises(TypeError, context.set_timeout, 1, None)
689
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400690 def test_get_timeout_wrong_args(self):
691 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200692 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with
693 any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400694 """
695 context = Context(TLSv1_METHOD)
696 self.assertRaises(TypeError, context.get_timeout, None)
697
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400698 def test_timeout(self):
699 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200700 :py:obj:`Context.set_timeout` sets the session timeout for all
701 connections created using the context object.
702 :py:obj:`Context.get_timeout` retrieves this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400703 """
704 context = Context(TLSv1_METHOD)
705 context.set_timeout(1234)
706 self.assertEquals(context.get_timeout(), 1234)
707
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500708 if not PY3:
709 def test_timeout_long(self):
710 """
711 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
712 `long` as well as int.
713 """
714 context = Context(TLSv1_METHOD)
715 context.set_timeout(long(1234))
716 self.assertEquals(context.get_timeout(), 1234)
717
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400718 def test_set_verify_depth_wrong_args(self):
719 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200720 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called
721 with the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400722 """
723 context = Context(TLSv1_METHOD)
724 self.assertRaises(TypeError, context.set_verify_depth)
725 self.assertRaises(TypeError, context.set_verify_depth, None)
726 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
727
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400728 def test_get_verify_depth_wrong_args(self):
729 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200730 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called
731 with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400732 """
733 context = Context(TLSv1_METHOD)
734 self.assertRaises(TypeError, context.get_verify_depth, None)
735
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400736 def test_verify_depth(self):
737 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200738 :py:obj:`Context.set_verify_depth` sets the number of certificates in
739 a chain to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900740 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400741 """
742 context = Context(TLSv1_METHOD)
743 context.set_verify_depth(11)
744 self.assertEquals(context.get_verify_depth(), 11)
745
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500746 if not PY3:
747 def test_verify_depth_long(self):
748 """
749 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
750 type `long` as well as int.
751 """
752 context = Context(TLSv1_METHOD)
753 context.set_verify_depth(long(11))
754 self.assertEquals(context.get_verify_depth(), 11)
755
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400756 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400757 """
758 Write a new private key out to a new file, encrypted using the given
759 passphrase. Return the path to the new file.
760 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400761 key = PKey()
762 key.generate_key(TYPE_RSA, 128)
763 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400764 fObj = open(pemFile, 'w')
765 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
766 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400767 fObj.close()
768 return pemFile
769
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400770 def test_set_passwd_cb_wrong_args(self):
771 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200772 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called
773 with the wrong arguments or with a non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400774 """
775 context = Context(TLSv1_METHOD)
776 self.assertRaises(TypeError, context.set_passwd_cb)
777 self.assertRaises(TypeError, context.set_passwd_cb, None)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200778 self.assertRaises(
779 TypeError, context.set_passwd_cb, lambda: None, None, None
780 )
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400781
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400782 def test_set_passwd_cb(self):
783 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200784 :py:obj:`Context.set_passwd_cb` accepts a callable which will be
785 invoked when a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400786 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400787 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400788 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400789 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200790
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400791 def passphraseCallback(maxlen, verify, extra):
792 calledWith.append((maxlen, verify, extra))
793 return passphrase
794 context = Context(TLSv1_METHOD)
795 context.set_passwd_cb(passphraseCallback)
796 context.use_privatekey_file(pemFile)
797 self.assertTrue(len(calledWith), 1)
798 self.assertTrue(isinstance(calledWith[0][0], int))
799 self.assertTrue(isinstance(calledWith[0][1], int))
800 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400801
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400802 def test_passwd_callback_exception(self):
803 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200804 :py:obj:`Context.use_privatekey_file` propagates any exception raised
805 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400806 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400807 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200808
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400809 def passphraseCallback(maxlen, verify, extra):
810 raise RuntimeError("Sorry, I am a fail.")
811
812 context = Context(TLSv1_METHOD)
813 context.set_passwd_cb(passphraseCallback)
814 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
815
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400816 def test_passwd_callback_false(self):
817 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200818 :py:obj:`Context.use_privatekey_file` raises
819 :py:obj:`OpenSSL.SSL.Error` if the passphrase callback returns a false
820 value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400821 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400822 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200823
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400824 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500825 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400826
827 context = Context(TLSv1_METHOD)
828 context.set_passwd_cb(passphraseCallback)
829 self.assertRaises(Error, context.use_privatekey_file, pemFile)
830
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400831 def test_passwd_callback_non_string(self):
832 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200833 :py:obj:`Context.use_privatekey_file` raises
834 :py:obj:`OpenSSL.SSL.Error` if the passphrase callback returns a true
835 non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400836 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400837 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200838
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400839 def passphraseCallback(maxlen, verify, extra):
840 return 10
841
842 context = Context(TLSv1_METHOD)
843 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800844 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400845
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400846 def test_passwd_callback_too_long(self):
847 """
848 If the passphrase returned by the passphrase callback returns a string
849 longer than the indicated maximum length, it is truncated.
850 """
851 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400852 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400853 pemFile = self._write_encrypted_pem(passphrase)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200854
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400855 def passphraseCallback(maxlen, verify, extra):
856 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400857 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400858
859 context = Context(TLSv1_METHOD)
860 context.set_passwd_cb(passphraseCallback)
861 # This shall succeed because the truncated result is the correct
862 # passphrase.
863 context.use_privatekey_file(pemFile)
864
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400865 def test_set_info_callback(self):
866 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200867 :py:obj:`Context.set_info_callback` accepts a callable which will be
868 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400869 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500870 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400871
872 clientSSL = Connection(Context(TLSv1_METHOD), client)
873 clientSSL.set_connect_state()
874
875 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200876
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400877 def info(conn, where, ret):
878 called.append((conn, where, ret))
879 context = Context(TLSv1_METHOD)
880 context.set_info_callback(info)
881 context.use_certificate(
882 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
883 context.use_privatekey(
884 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
885
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400886 serverSSL = Connection(context, server)
887 serverSSL.set_accept_state()
888
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500889 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400890
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500891 # The callback must always be called with a Connection instance as the
892 # first argument. It would probably be better to split this into
893 # separate tests for client and server side info callbacks so we could
894 # assert it is called with the right Connection instance. It would
895 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500896 notConnections = [
897 conn for (conn, where, ret) in called
898 if not isinstance(conn, Connection)]
899 self.assertEqual(
900 [], notConnections,
901 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400902
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400903 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400904 """
905 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400906 its :py:obj:`load_verify_locations` method with the given arguments.
907 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400908 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500909 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400910
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400911 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400912 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400913 # Require that the server certificate verify properly or the
914 # connection will fail.
915 clientContext.set_verify(
916 VERIFY_PEER,
917 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
918
919 clientSSL = Connection(clientContext, client)
920 clientSSL.set_connect_state()
921
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400922 serverContext = Context(TLSv1_METHOD)
923 serverContext.use_certificate(
924 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
925 serverContext.use_privatekey(
926 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
927
928 serverSSL = Connection(serverContext, server)
929 serverSSL.set_accept_state()
930
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400931 # Without load_verify_locations above, the handshake
932 # will fail:
933 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
934 # 'certificate verify failed')]
935 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400936
937 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400938 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400939
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400940 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400941 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400942 Verify that if path to a file containing a certificate is passed to
943 ``Context.load_verify_locations`` for the ``cafile`` parameter, that
944 certificate is used as a trust root for the purposes of verifying
945 connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400946 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400947 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400948 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400949 fObj.close()
950
951 self._load_verify_locations_test(cafile)
952
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400953 def test_load_verify_bytes_cafile(self):
954 """
955 :py:obj:`Context.load_verify_locations` accepts a file name as a
956 ``bytes`` instance and uses the certificates within for verification
957 purposes.
958 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400959 cafile = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400960 self._load_verify_cafile(cafile)
961
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400962 def test_load_verify_unicode_cafile(self):
963 """
964 :py:obj:`Context.load_verify_locations` accepts a file name as a
965 ``unicode`` instance and uses the certificates within for verification
966 purposes.
967 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -0400968 self._load_verify_cafile(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400969 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -0400970 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400971
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400972 def test_load_verify_invalid_file(self):
973 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200974 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when
975 passed a non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400976 """
977 clientContext = Context(TLSv1_METHOD)
978 self.assertRaises(
979 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400980
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400981 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400982 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400983 Verify that if path to a directory containing certificate files is
984 passed to ``Context.load_verify_locations`` for the ``capath``
985 parameter, those certificates are used as trust roots for the purposes
986 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400987 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400988 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400989 # Hash values computed manually with c_rehash to avoid depending on
990 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
991 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500992 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400993 cafile = join_bytes_or_unicode(capath, name)
994 with open(cafile, 'w') as fObj:
995 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400996
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400997 self._load_verify_locations_test(None, capath)
998
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400999 def test_load_verify_directory_bytes_capath(self):
1000 """
1001 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1002 ``bytes`` instance and uses the certificates within for verification
1003 purposes.
1004 """
1005 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001006 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001007 )
1008
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001009 def test_load_verify_directory_unicode_capath(self):
1010 """
1011 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1012 ``unicode`` instance and uses the certificates within for verification
1013 purposes.
1014 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001015 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001016 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001017 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001018
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001019 def test_load_verify_locations_wrong_args(self):
1020 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001021 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if
1022 called with the wrong number of arguments or with non-:py:obj:`str`
1023 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001024 """
1025 context = Context(TLSv1_METHOD)
1026 self.assertRaises(TypeError, context.load_verify_locations)
1027 self.assertRaises(TypeError, context.load_verify_locations, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001028 self.assertRaises(
1029 TypeError, context.load_verify_locations, object(), object()
1030 )
1031 self.assertRaises(
1032 TypeError, context.load_verify_locations, None, None, None
1033 )
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001034
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001035 if platform == "win32":
1036 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001037 "See LP#404343 and LP#404344."
1038 else:
1039 def test_set_default_verify_paths(self):
1040 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001041 :py:obj:`Context.set_default_verify_paths` causes the
1042 platform-specific CA certificate locations to be used for
1043 verification purposes.
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001044 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001045 # Testing this requires a server with a certificate signed by one
1046 # of the CAs in the platform CA location. Getting one of those
1047 # costs money. Fortunately (or unfortunately, depending on your
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001048 # perspective), it's easy to think of a public server on the
1049 # internet which has such a certificate. Connecting to the network
1050 # in a unit test is bad, but it's the only way I can think of to
1051 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001052
Alex Gaynorb586da32014-11-15 09:22:21 -08001053 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
1054 context = Context(TLSv1_METHOD)
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001055 context.set_default_verify_paths()
1056 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02001057 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001058 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001059
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001060 client = socket()
1061 client.connect(('verisign.com', 443))
1062 clientSSL = Connection(context, client)
1063 clientSSL.set_connect_state()
1064 clientSSL.do_handshake()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001065 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001066 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001067
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001068 def test_set_default_verify_paths_signature(self):
1069 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001070 :py:obj:`Context.set_default_verify_paths` takes no arguments and
1071 raises :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001072 """
1073 context = Context(TLSv1_METHOD)
1074 self.assertRaises(TypeError, context.set_default_verify_paths, None)
1075 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
1076 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001077
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001078 def test_add_extra_chain_cert_invalid_cert(self):
1079 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001080 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if
1081 called with other than one argument or if called with an object which
1082 is not an instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001083 """
1084 context = Context(TLSv1_METHOD)
1085 self.assertRaises(TypeError, context.add_extra_chain_cert)
1086 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001087 self.assertRaises(
1088 TypeError, context.add_extra_chain_cert, object(), object()
1089 )
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001090
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001091 def _handshake_test(self, serverContext, clientContext):
1092 """
1093 Verify that a client and server created with the given contexts can
1094 successfully handshake and communicate.
1095 """
1096 serverSocket, clientSocket = socket_pair()
1097
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001098 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001099 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001100
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001101 client = Connection(clientContext, clientSocket)
1102 client.set_connect_state()
1103
1104 # Make them talk to each other.
1105 # self._interactInMemory(client, server)
1106 for i in range(3):
1107 for s in [client, server]:
1108 try:
1109 s.do_handshake()
1110 except WantReadError:
1111 pass
1112
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001113 def test_set_verify_callback_connection_argument(self):
1114 """
1115 The first argument passed to the verify callback is the
1116 :py:class:`Connection` instance for which verification is taking place.
1117 """
1118 serverContext = Context(TLSv1_METHOD)
1119 serverContext.use_privatekey(
1120 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1121 serverContext.use_certificate(
1122 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1123 serverConnection = Connection(serverContext, None)
1124
1125 class VerifyCallback(object):
1126 def callback(self, connection, *args):
1127 self.connection = connection
1128 return 1
1129
1130 verify = VerifyCallback()
1131 clientContext = Context(TLSv1_METHOD)
1132 clientContext.set_verify(VERIFY_PEER, verify.callback)
1133 clientConnection = Connection(clientContext, None)
1134 clientConnection.set_connect_state()
1135
1136 self._handshakeInMemory(clientConnection, serverConnection)
1137
1138 self.assertIdentical(verify.connection, clientConnection)
1139
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001140 def test_set_verify_callback_exception(self):
1141 """
1142 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1143 exception, verification fails and the exception is propagated to the
1144 caller of :py:obj:`Connection.do_handshake`.
1145 """
1146 serverContext = Context(TLSv1_METHOD)
1147 serverContext.use_privatekey(
1148 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1149 serverContext.use_certificate(
1150 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1151
1152 clientContext = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001153
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001154 def verify_callback(*args):
1155 raise Exception("silly verify failure")
1156 clientContext.set_verify(VERIFY_PEER, verify_callback)
1157
1158 exc = self.assertRaises(
1159 Exception, self._handshake_test, serverContext, clientContext)
1160 self.assertEqual("silly verify failure", str(exc))
1161
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001162 def test_add_extra_chain_cert(self):
1163 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001164 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509`
1165 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001166
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001167 See :py:obj:`_create_certificate_chain` for the details of the
1168 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001169
1170 The chain is tested by starting a server with scert and connecting
1171 to it with a client which trusts cacert and requires verification to
1172 succeed.
1173 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001174 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001175 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1176
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001177 # Dump the CA certificate to a file because that's the only way to load
1178 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001179 for cert, name in [(cacert, 'ca.pem'),
1180 (icert, 'i.pem'),
1181 (scert, 's.pem')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001182 with open(join(self.tmpdir, name), 'w') as f:
1183 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001184
Hynek Schlawack1902c012015-04-16 15:06:41 -04001185 for key, name in [(cakey, 'ca.key'),
1186 (ikey, 'i.key'),
1187 (skey, 's.key')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001188 with open(join(self.tmpdir, name), 'w') as f:
1189 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001190
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001191 # Create the server context
1192 serverContext = Context(TLSv1_METHOD)
1193 serverContext.use_privatekey(skey)
1194 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001195 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001196 serverContext.add_extra_chain_cert(icert)
1197
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001198 # Create the client
1199 clientContext = Context(TLSv1_METHOD)
1200 clientContext.set_verify(
1201 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001202 clientContext.load_verify_locations(join(self.tmpdir, "ca.pem"))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001203
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001204 # Try it out.
1205 self._handshake_test(serverContext, clientContext)
1206
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001207 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001208 """
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001209 Verify that :py:obj:`Context.use_certificate_chain_file` reads a
1210 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001211
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001212 The chain is tested by starting a server with scert and connecting to
1213 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001214 succeed.
1215 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001216 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001217 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1218
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001219 makedirs(certdir)
1220
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001221 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1222 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001223
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001224 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001225 with open(chainFile, 'wb') as fObj:
1226 # Most specific to least general.
1227 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1228 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1229 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1230
1231 with open(caFile, 'w') as fObj:
1232 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001233
1234 serverContext = Context(TLSv1_METHOD)
1235 serverContext.use_certificate_chain_file(chainFile)
1236 serverContext.use_privatekey(skey)
1237
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001238 clientContext = Context(TLSv1_METHOD)
1239 clientContext.set_verify(
1240 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001241 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001242
1243 self._handshake_test(serverContext, clientContext)
1244
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001245 def test_use_certificate_chain_file_bytes(self):
1246 """
1247 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1248 an instance of ``bytes``) to specify additional certificates to use to
1249 construct and verify a trust chain.
1250 """
1251 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001252 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001253 )
1254
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001255 def test_use_certificate_chain_file_unicode(self):
1256 """
1257 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1258 an instance of ``unicode``) to specify additional certificates to use
1259 to construct and verify a trust chain.
1260 """
1261 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001262 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001263 )
1264
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001265 def test_use_certificate_chain_file_wrong_args(self):
1266 """
1267 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1268 if passed zero or more than one argument or when passed a non-byte
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001269 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error`
1270 when passed a bad chain file name (for example, the name of a file
1271 which does not exist).
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001272 """
1273 context = Context(TLSv1_METHOD)
1274 self.assertRaises(TypeError, context.use_certificate_chain_file)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001275 self.assertRaises(
1276 TypeError, context.use_certificate_chain_file, object()
1277 )
1278 self.assertRaises(
1279 TypeError, context.use_certificate_chain_file, b"foo", object()
1280 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001281
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001282 self.assertRaises(
1283 Error, context.use_certificate_chain_file, self.mktemp()
1284 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001285
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001286 # XXX load_client_ca
1287 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001288
1289 def test_get_verify_mode_wrong_args(self):
1290 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001291 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called
1292 with any arguments.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001293 """
1294 context = Context(TLSv1_METHOD)
1295 self.assertRaises(TypeError, context.get_verify_mode, None)
1296
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001297 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001298 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001299 :py:obj:`Context.get_verify_mode` returns the verify mode flags
1300 previously passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001301 """
1302 context = Context(TLSv1_METHOD)
1303 self.assertEquals(context.get_verify_mode(), 0)
1304 context.set_verify(
1305 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1306 self.assertEquals(
1307 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1308
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001309 if not PY3:
1310 def test_set_verify_mode_long(self):
1311 """
1312 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1313 type :py:obj:`long` as well as :py:obj:`int`.
1314 """
1315 context = Context(TLSv1_METHOD)
1316 self.assertEquals(context.get_verify_mode(), 0)
1317 context.set_verify(
1318 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None)
1319 self.assertEquals(
1320 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1321
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001322 def test_load_tmp_dh_wrong_args(self):
1323 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001324 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with
1325 the wrong number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001326 """
1327 context = Context(TLSv1_METHOD)
1328 self.assertRaises(TypeError, context.load_tmp_dh)
1329 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1330 self.assertRaises(TypeError, context.load_tmp_dh, object())
1331
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001332 def test_load_tmp_dh_missing_file(self):
1333 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001334 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the
1335 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001336 """
1337 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001338 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001339
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001340 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001341 """
1342 Verify that calling ``Context.load_tmp_dh`` with the given filename
1343 does not raise an exception.
1344 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001345 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001346 with open(dhfilename, "w") as dhfile:
1347 dhfile.write(dhparam)
1348
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001349 context.load_tmp_dh(dhfilename)
1350 # XXX What should I assert here? -exarkun
1351
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001352 def test_load_tmp_dh_bytes(self):
1353 """
1354 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1355 specified file (given as ``bytes``).
1356 """
1357 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001358 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001359 )
1360
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001361 def test_load_tmp_dh_unicode(self):
1362 """
1363 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1364 specified file (given as ``unicode``).
1365 """
1366 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001367 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001368 )
1369
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001370 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001371 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001372 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001373 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001374 """
1375 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001376 for curve in get_elliptic_curves():
1377 # The only easily "assertable" thing is that it does not raise an
1378 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001379 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001380
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001381 def test_set_cipher_list_bytes(self):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001382 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001383 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
1384 ciphers which connections created with the context object will be able
1385 to choose from.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001386 """
1387 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001388 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001389 conn = Connection(context, None)
1390 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001391
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001392 def test_set_cipher_list_text(self):
1393 """
1394 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
1395 the ciphers which connections created with the context object will be
1396 able to choose from.
1397 """
1398 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -05001399 context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001400 conn = Connection(context, None)
1401 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
1402
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001403 def test_set_cipher_list_wrong_args(self):
1404 """
Jean-Paul Calderone17044832014-01-18 10:20:11 -05001405 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
1406 passed zero arguments or more than one argument or when passed a
1407 non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001408 passed an incorrect cipher list string.
1409 """
1410 context = Context(TLSv1_METHOD)
1411 self.assertRaises(TypeError, context.set_cipher_list)
1412 self.assertRaises(TypeError, context.set_cipher_list, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001413 self.assertRaises(
1414 TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object()
1415 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001416
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001417 self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001418
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001419 def test_set_session_cache_mode_wrong_args(self):
1420 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001421 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1422 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001423 """
1424 context = Context(TLSv1_METHOD)
1425 self.assertRaises(TypeError, context.set_session_cache_mode)
1426 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1427
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001428 def test_get_session_cache_mode_wrong_args(self):
1429 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001430 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1431 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001432 """
1433 context = Context(TLSv1_METHOD)
1434 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1435
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001436 def test_session_cache_mode(self):
1437 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001438 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1439 cached. The setting can be retrieved via
1440 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001441 """
1442 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001443 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001444 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1445 self.assertEqual(SESS_CACHE_OFF, off)
1446 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1447
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001448 if not PY3:
1449 def test_session_cache_mode_long(self):
1450 """
1451 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1452 of type :py:obj:`long` as well as :py:obj:`int`.
1453 """
1454 context = Context(TLSv1_METHOD)
1455 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1456 self.assertEqual(
1457 SESS_CACHE_BOTH, context.get_session_cache_mode())
1458
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001459 def test_get_cert_store(self):
1460 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001461 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store`
1462 instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001463 """
1464 context = Context(TLSv1_METHOD)
1465 store = context.get_cert_store()
1466 self.assertIsInstance(store, X509Store)
1467
1468
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001469class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1470 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001471 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
1472 :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001473 """
1474 def test_wrong_args(self):
1475 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001476 :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001477 with other than one argument.
1478 """
1479 context = Context(TLSv1_METHOD)
1480 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1481 self.assertRaises(
1482 TypeError, context.set_tlsext_servername_callback, 1, 2)
1483
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001484
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001485 def test_old_callback_forgotten(self):
1486 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001487 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001488 callback, the one it replaces is dereferenced.
1489 """
1490 def callback(connection):
1491 pass
1492
1493 def replacement(connection):
1494 pass
1495
1496 context = Context(TLSv1_METHOD)
1497 context.set_tlsext_servername_callback(callback)
1498
1499 tracker = ref(callback)
1500 del callback
1501
1502 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001503
1504 # One run of the garbage collector happens to work on CPython. PyPy
1505 # doesn't collect the underlying object until a second run for whatever
1506 # reason. That's fine, it still demonstrates our code has properly
1507 # dropped the reference.
1508 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001509 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001510
1511 callback = tracker()
1512 if callback is not None:
1513 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001514 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001515 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001516
1517
1518 def test_no_servername(self):
1519 """
1520 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001521 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
1522 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001523 """
1524 args = []
1525 def servername(conn):
1526 args.append((conn, conn.get_servername()))
1527 context = Context(TLSv1_METHOD)
1528 context.set_tlsext_servername_callback(servername)
1529
1530 # Lose our reference to it. The Context is responsible for keeping it
1531 # alive now.
1532 del servername
1533 collect()
1534
1535 # Necessary to actually accept the connection
1536 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1537 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1538
1539 # Do a little connection to trigger the logic
1540 server = Connection(context, None)
1541 server.set_accept_state()
1542
1543 client = Connection(Context(TLSv1_METHOD), None)
1544 client.set_connect_state()
1545
1546 self._interactInMemory(server, client)
1547
1548 self.assertEqual([(server, None)], args)
1549
1550
1551 def test_servername(self):
1552 """
1553 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +09001554 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
1555 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001556 """
1557 args = []
1558 def servername(conn):
1559 args.append((conn, conn.get_servername()))
1560 context = Context(TLSv1_METHOD)
1561 context.set_tlsext_servername_callback(servername)
1562
1563 # Necessary to actually accept the connection
1564 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1565 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1566
1567 # Do a little connection to trigger the logic
1568 server = Connection(context, None)
1569 server.set_accept_state()
1570
1571 client = Connection(Context(TLSv1_METHOD), None)
1572 client.set_connect_state()
1573 client.set_tlsext_host_name(b("foo1.example.com"))
1574
1575 self._interactInMemory(server, client)
1576
1577 self.assertEqual([(server, b("foo1.example.com"))], args)
1578
1579
Cory Benfield84a121e2014-03-31 20:30:25 +01001580class NextProtoNegotiationTests(TestCase, _LoopbackMixin):
1581 """
1582 Test for Next Protocol Negotiation in PyOpenSSL.
1583 """
Cory Benfieldba1820d2015-04-13 17:39:12 -04001584 if _lib.Cryptography_HAS_NEXTPROTONEG:
1585 def test_npn_success(self):
1586 """
1587 Tests that clients and servers that agree on the negotiated next
1588 protocol can correct establish a connection, and that the agreed
1589 protocol is reported by the connections.
1590 """
1591 advertise_args = []
1592 select_args = []
1593 def advertise(conn):
1594 advertise_args.append((conn,))
1595 return [b'http/1.1', b'spdy/2']
1596 def select(conn, options):
1597 select_args.append((conn, options))
1598 return b'spdy/2'
Cory Benfield84a121e2014-03-31 20:30:25 +01001599
Cory Benfieldba1820d2015-04-13 17:39:12 -04001600 server_context = Context(TLSv1_METHOD)
1601 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001602
Cory Benfieldba1820d2015-04-13 17:39:12 -04001603 client_context = Context(TLSv1_METHOD)
1604 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001605
Cory Benfieldba1820d2015-04-13 17:39:12 -04001606 # Necessary to actually accept the connection
1607 server_context.use_privatekey(
1608 load_privatekey(FILETYPE_PEM, server_key_pem))
1609 server_context.use_certificate(
1610 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001611
Cory Benfieldba1820d2015-04-13 17:39:12 -04001612 # Do a little connection to trigger the logic
1613 server = Connection(server_context, None)
1614 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001615
Cory Benfieldba1820d2015-04-13 17:39:12 -04001616 client = Connection(client_context, None)
1617 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001618
Cory Benfieldba1820d2015-04-13 17:39:12 -04001619 self._interactInMemory(server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001620
Cory Benfieldba1820d2015-04-13 17:39:12 -04001621 self.assertEqual([(server,)], advertise_args)
1622 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001623
Cory Benfieldba1820d2015-04-13 17:39:12 -04001624 self.assertEqual(server.get_next_proto_negotiated(), b'spdy/2')
1625 self.assertEqual(client.get_next_proto_negotiated(), b'spdy/2')
Cory Benfield84a121e2014-03-31 20:30:25 +01001626
1627
Cory Benfieldba1820d2015-04-13 17:39:12 -04001628 def test_npn_client_fail(self):
1629 """
1630 Tests that when clients and servers cannot agree on what protocol
1631 to use next that the TLS connection does not get established.
1632 """
1633 advertise_args = []
1634 select_args = []
1635 def advertise(conn):
1636 advertise_args.append((conn,))
1637 return [b'http/1.1', b'spdy/2']
1638 def select(conn, options):
1639 select_args.append((conn, options))
1640 return b''
Cory Benfield84a121e2014-03-31 20:30:25 +01001641
Cory Benfieldba1820d2015-04-13 17:39:12 -04001642 server_context = Context(TLSv1_METHOD)
1643 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001644
Cory Benfieldba1820d2015-04-13 17:39:12 -04001645 client_context = Context(TLSv1_METHOD)
1646 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001647
Cory Benfieldba1820d2015-04-13 17:39:12 -04001648 # Necessary to actually accept the connection
1649 server_context.use_privatekey(
1650 load_privatekey(FILETYPE_PEM, server_key_pem))
1651 server_context.use_certificate(
1652 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001653
Cory Benfieldba1820d2015-04-13 17:39:12 -04001654 # Do a little connection to trigger the logic
1655 server = Connection(server_context, None)
1656 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001657
Cory Benfieldba1820d2015-04-13 17:39:12 -04001658 client = Connection(client_context, None)
1659 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001660
Cory Benfieldba1820d2015-04-13 17:39:12 -04001661 # If the client doesn't return anything, the connection will fail.
1662 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001663
Cory Benfieldba1820d2015-04-13 17:39:12 -04001664 self.assertEqual([(server,)], advertise_args)
1665 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001666
1667
Cory Benfieldba1820d2015-04-13 17:39:12 -04001668 def test_npn_select_error(self):
1669 """
1670 Test that we can handle exceptions in the select callback. If
1671 select fails it should be fatal to the connection.
1672 """
1673 advertise_args = []
1674 def advertise(conn):
1675 advertise_args.append((conn,))
1676 return [b'http/1.1', b'spdy/2']
1677 def select(conn, options):
1678 raise TypeError
Cory Benfield0ea76e72015-03-22 09:05:28 +00001679
Cory Benfieldba1820d2015-04-13 17:39:12 -04001680 server_context = Context(TLSv1_METHOD)
1681 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001682
Cory Benfieldba1820d2015-04-13 17:39:12 -04001683 client_context = Context(TLSv1_METHOD)
1684 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001685
Cory Benfieldba1820d2015-04-13 17:39:12 -04001686 # Necessary to actually accept the connection
1687 server_context.use_privatekey(
1688 load_privatekey(FILETYPE_PEM, server_key_pem))
1689 server_context.use_certificate(
1690 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001691
Cory Benfieldba1820d2015-04-13 17:39:12 -04001692 # Do a little connection to trigger the logic
1693 server = Connection(server_context, None)
1694 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001695
Cory Benfieldba1820d2015-04-13 17:39:12 -04001696 client = Connection(client_context, None)
1697 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001698
Cory Benfieldba1820d2015-04-13 17:39:12 -04001699 # If the callback throws an exception it should be raised here.
1700 self.assertRaises(
1701 TypeError, self._interactInMemory, server, client
1702 )
1703 self.assertEqual([(server,)], advertise_args)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001704
1705
Cory Benfieldba1820d2015-04-13 17:39:12 -04001706 def test_npn_advertise_error(self):
1707 """
1708 Test that we can handle exceptions in the advertise callback. If
1709 advertise fails no NPN is advertised to the client.
1710 """
1711 select_args = []
1712 def advertise(conn):
1713 raise TypeError
1714 def select(conn, options):
1715 select_args.append((conn, options))
1716 return b''
Cory Benfield0ea76e72015-03-22 09:05:28 +00001717
Cory Benfieldba1820d2015-04-13 17:39:12 -04001718 server_context = Context(TLSv1_METHOD)
1719 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001720
Cory Benfieldba1820d2015-04-13 17:39:12 -04001721 client_context = Context(TLSv1_METHOD)
1722 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001723
Cory Benfieldba1820d2015-04-13 17:39:12 -04001724 # Necessary to actually accept the connection
1725 server_context.use_privatekey(
1726 load_privatekey(FILETYPE_PEM, server_key_pem))
1727 server_context.use_certificate(
1728 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001729
Cory Benfieldba1820d2015-04-13 17:39:12 -04001730 # Do a little connection to trigger the logic
1731 server = Connection(server_context, None)
1732 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001733
Cory Benfieldba1820d2015-04-13 17:39:12 -04001734 client = Connection(client_context, None)
1735 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001736
Cory Benfieldba1820d2015-04-13 17:39:12 -04001737 # If the client doesn't return anything, the connection will fail.
1738 self.assertRaises(
1739 TypeError, self._interactInMemory, server, client
1740 )
1741 self.assertEqual([], select_args)
1742
1743 else:
1744 # No NPN.
1745 def test_npn_not_implemented(self):
1746 # Test the context methods first.
1747 context = Context(TLSv1_METHOD)
1748 fail_methods = [
1749 context.set_npn_advertise_callback,
1750 context.set_npn_select_callback,
1751 ]
1752 for method in fail_methods:
1753 self.assertRaises(
1754 NotImplementedError, method, None
1755 )
1756
1757 # Now test a connection.
1758 conn = Connection(context)
1759 fail_methods = [
1760 conn.get_next_proto_negotiated,
1761 ]
1762 for method in fail_methods:
1763 self.assertRaises(NotImplementedError, method)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001764
1765
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001766
Cory Benfield12eae892014-06-07 15:42:56 +01001767class ApplicationLayerProtoNegotiationTests(TestCase, _LoopbackMixin):
1768 """
1769 Tests for ALPN in PyOpenSSL.
1770 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001771 # Skip tests on versions that don't support ALPN.
1772 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001773
Cory Benfielde46fa842015-04-13 16:50:49 -04001774 def test_alpn_success(self):
1775 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001776 Clients and servers that agree on the negotiated ALPN protocol can
1777 correct establish a connection, and the agreed protocol is reported
1778 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001779 """
1780 select_args = []
1781 def select(conn, options):
1782 select_args.append((conn, options))
1783 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001784
Cory Benfielde46fa842015-04-13 16:50:49 -04001785 client_context = Context(TLSv1_METHOD)
1786 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001787
Cory Benfielde46fa842015-04-13 16:50:49 -04001788 server_context = Context(TLSv1_METHOD)
1789 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001790
Cory Benfielde46fa842015-04-13 16:50:49 -04001791 # Necessary to actually accept the connection
1792 server_context.use_privatekey(
1793 load_privatekey(FILETYPE_PEM, server_key_pem))
1794 server_context.use_certificate(
1795 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001796
Cory Benfielde46fa842015-04-13 16:50:49 -04001797 # Do a little connection to trigger the logic
1798 server = Connection(server_context, None)
1799 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001800
Cory Benfielde46fa842015-04-13 16:50:49 -04001801 client = Connection(client_context, None)
1802 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001803
Cory Benfielde46fa842015-04-13 16:50:49 -04001804 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001805
Cory Benfielde46fa842015-04-13 16:50:49 -04001806 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
1807
1808 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1809 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001810
1811
Cory Benfielde46fa842015-04-13 16:50:49 -04001812 def test_alpn_set_on_connection(self):
1813 """
1814 The same as test_alpn_success, but setting the ALPN protocols on
1815 the connection rather than the context.
1816 """
1817 select_args = []
1818 def select(conn, options):
1819 select_args.append((conn, options))
1820 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001821
Cory Benfielde46fa842015-04-13 16:50:49 -04001822 # Setup the client context but don't set any ALPN protocols.
1823 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001824
Cory Benfielde46fa842015-04-13 16:50:49 -04001825 server_context = Context(TLSv1_METHOD)
1826 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001827
Cory Benfielde46fa842015-04-13 16:50:49 -04001828 # Necessary to actually accept the connection
1829 server_context.use_privatekey(
1830 load_privatekey(FILETYPE_PEM, server_key_pem))
1831 server_context.use_certificate(
1832 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001833
Cory Benfielde46fa842015-04-13 16:50:49 -04001834 # Do a little connection to trigger the logic
1835 server = Connection(server_context, None)
1836 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001837
Cory Benfielde46fa842015-04-13 16:50:49 -04001838 # Set the ALPN protocols on the client connection.
1839 client = Connection(client_context, None)
1840 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1841 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001842
Cory Benfielde46fa842015-04-13 16:50:49 -04001843 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001844
Cory Benfielde46fa842015-04-13 16:50:49 -04001845 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001846
Cory Benfielde46fa842015-04-13 16:50:49 -04001847 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1848 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001849
1850
Cory Benfielde46fa842015-04-13 16:50:49 -04001851 def test_alpn_server_fail(self):
1852 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001853 When clients and servers cannot agree on what protocol to use next
1854 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001855 """
1856 select_args = []
1857 def select(conn, options):
1858 select_args.append((conn, options))
1859 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001860
Cory Benfielde46fa842015-04-13 16:50:49 -04001861 client_context = Context(TLSv1_METHOD)
1862 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001863
Cory Benfielde46fa842015-04-13 16:50:49 -04001864 server_context = Context(TLSv1_METHOD)
1865 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001866
Cory Benfielde46fa842015-04-13 16:50:49 -04001867 # Necessary to actually accept the connection
1868 server_context.use_privatekey(
1869 load_privatekey(FILETYPE_PEM, server_key_pem))
1870 server_context.use_certificate(
1871 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001872
Cory Benfielde46fa842015-04-13 16:50:49 -04001873 # Do a little connection to trigger the logic
1874 server = Connection(server_context, None)
1875 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001876
Cory Benfielde46fa842015-04-13 16:50:49 -04001877 client = Connection(client_context, None)
1878 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001879
Cory Benfielde46fa842015-04-13 16:50:49 -04001880 # If the client doesn't return anything, the connection will fail.
1881 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001882
Cory Benfielde46fa842015-04-13 16:50:49 -04001883 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001884
1885
Cory Benfielde46fa842015-04-13 16:50:49 -04001886 def test_alpn_no_server(self):
1887 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001888 When clients and servers cannot agree on what protocol to use next
1889 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04001890 """
1891 client_context = Context(TLSv1_METHOD)
1892 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04001893
Cory Benfielde46fa842015-04-13 16:50:49 -04001894 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04001895
Cory Benfielde46fa842015-04-13 16:50:49 -04001896 # Necessary to actually accept the connection
1897 server_context.use_privatekey(
1898 load_privatekey(FILETYPE_PEM, server_key_pem))
1899 server_context.use_certificate(
1900 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04001901
Cory Benfielde46fa842015-04-13 16:50:49 -04001902 # Do a little connection to trigger the logic
1903 server = Connection(server_context, None)
1904 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001905
Cory Benfielde46fa842015-04-13 16:50:49 -04001906 client = Connection(client_context, None)
1907 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001908
Cory Benfielde46fa842015-04-13 16:50:49 -04001909 # Do the dance.
1910 self._interactInMemory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04001911
Cory Benfielde46fa842015-04-13 16:50:49 -04001912 self.assertEqual(client.get_alpn_proto_negotiated(), b'')
Cory Benfielde3d57152015-04-11 17:57:35 -04001913
1914
Cory Benfielde46fa842015-04-13 16:50:49 -04001915 def test_alpn_callback_exception(self):
1916 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001917 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04001918 """
1919 select_args = []
1920 def select(conn, options):
1921 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04001922 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001923
Cory Benfielde46fa842015-04-13 16:50:49 -04001924 client_context = Context(TLSv1_METHOD)
1925 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04001926
Cory Benfielde46fa842015-04-13 16:50:49 -04001927 server_context = Context(TLSv1_METHOD)
1928 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04001929
Cory Benfielde46fa842015-04-13 16:50:49 -04001930 # Necessary to actually accept the connection
1931 server_context.use_privatekey(
1932 load_privatekey(FILETYPE_PEM, server_key_pem))
1933 server_context.use_certificate(
1934 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04001935
Cory Benfielde46fa842015-04-13 16:50:49 -04001936 # Do a little connection to trigger the logic
1937 server = Connection(server_context, None)
1938 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001939
Cory Benfielde46fa842015-04-13 16:50:49 -04001940 client = Connection(client_context, None)
1941 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001942
Cory Benfielde46fa842015-04-13 16:50:49 -04001943 self.assertRaises(
1944 TypeError, self._interactInMemory, server, client
1945 )
1946 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfieldf1177e72015-04-12 09:11:49 -04001947
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001948 else:
1949 # No ALPN.
1950 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04001951 """
1952 If ALPN is not in OpenSSL, we should raise NotImplementedError.
1953 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001954 # Test the context methods first.
1955 context = Context(TLSv1_METHOD)
Cory Benfield307e9e62015-04-13 18:21:12 -04001956 self.assertRaises(
1957 NotImplementedError, context.set_alpn_protos, None
1958 )
1959 self.assertRaises(
1960 NotImplementedError, context.set_alpn_select_callback, None
1961 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001962
1963 # Now test a connection.
1964 conn = Connection(context)
Cory Benfield307e9e62015-04-13 18:21:12 -04001965 self.assertRaises(
Alex Gaynor68417232015-09-04 07:56:29 -04001966 NotImplementedError, conn.set_alpn_protos, None
Cory Benfield307e9e62015-04-13 18:21:12 -04001967 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001968
Cory Benfieldf1177e72015-04-12 09:11:49 -04001969
Cory Benfield12eae892014-06-07 15:42:56 +01001970
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001971class SessionTests(TestCase):
1972 """
1973 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1974 """
1975 def test_construction(self):
1976 """
1977 :py:class:`Session` can be constructed with no arguments, creating a new
1978 instance of that type.
1979 """
1980 new_session = Session()
1981 self.assertTrue(isinstance(new_session, Session))
1982
1983
1984 def test_construction_wrong_args(self):
1985 """
1986 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
1987 is raised.
1988 """
1989 self.assertRaises(TypeError, Session, 123)
1990 self.assertRaises(TypeError, Session, "hello")
1991 self.assertRaises(TypeError, Session, object())
1992
1993
1994
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001995class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05001996 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001997 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001998 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001999 # XXX get_peer_certificate -> None
2000 # XXX sock_shutdown
2001 # XXX master_key -> TypeError
2002 # XXX server_random -> TypeError
2003 # XXX state_string
2004 # XXX connect -> TypeError
2005 # XXX connect_ex -> TypeError
2006 # XXX set_connect_state -> TypeError
2007 # XXX set_accept_state -> TypeError
2008 # XXX renegotiate_pending
2009 # XXX do_handshake -> TypeError
2010 # XXX bio_read -> TypeError
2011 # XXX recv -> TypeError
2012 # XXX send -> TypeError
2013 # XXX bio_write -> TypeError
2014
Rick Deane15b1472009-07-09 15:53:42 -05002015 def test_type(self):
2016 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002017 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002018 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002019 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002020 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05002021 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002022 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002023
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002024
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002025 def test_get_context(self):
2026 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002027 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
2028 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002029 """
2030 context = Context(TLSv1_METHOD)
2031 connection = Connection(context, None)
2032 self.assertIdentical(connection.get_context(), context)
2033
2034
2035 def test_get_context_wrong_args(self):
2036 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002037 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002038 arguments.
2039 """
2040 connection = Connection(Context(TLSv1_METHOD), None)
2041 self.assertRaises(TypeError, connection.get_context, None)
2042
2043
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002044 def test_set_context_wrong_args(self):
2045 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002046 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
2047 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002048 than 1.
2049 """
2050 ctx = Context(TLSv1_METHOD)
2051 connection = Connection(ctx, None)
2052 self.assertRaises(TypeError, connection.set_context)
2053 self.assertRaises(TypeError, connection.set_context, object())
2054 self.assertRaises(TypeError, connection.set_context, "hello")
2055 self.assertRaises(TypeError, connection.set_context, 1)
2056 self.assertRaises(TypeError, connection.set_context, 1, 2)
2057 self.assertRaises(
2058 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
2059 self.assertIdentical(ctx, connection.get_context())
2060
2061
2062 def test_set_context(self):
2063 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002064 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002065 for the connection.
2066 """
2067 original = Context(SSLv23_METHOD)
2068 replacement = Context(TLSv1_METHOD)
2069 connection = Connection(original, None)
2070 connection.set_context(replacement)
2071 self.assertIdentical(replacement, connection.get_context())
2072 # Lose our references to the contexts, just in case the Connection isn't
2073 # properly managing its own contributions to their reference counts.
2074 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002075 collect()
2076
2077
2078 def test_set_tlsext_host_name_wrong_args(self):
2079 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002080 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002081 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09002082 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002083 """
2084 conn = Connection(Context(TLSv1_METHOD), None)
2085 self.assertRaises(TypeError, conn.set_tlsext_host_name)
2086 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
2087 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
2088 self.assertRaises(
2089 TypeError, conn.set_tlsext_host_name, b("with\0null"))
2090
Abraham Martinc5484ba2015-03-25 15:33:05 +00002091 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002092 # On Python 3.x, don't accidentally implicitly convert from text.
2093 self.assertRaises(
2094 TypeError,
2095 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002096
2097
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002098 def test_get_servername_wrong_args(self):
2099 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002100 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002101 arguments.
2102 """
2103 connection = Connection(Context(TLSv1_METHOD), None)
2104 self.assertRaises(TypeError, connection.get_servername, object())
2105 self.assertRaises(TypeError, connection.get_servername, 1)
2106 self.assertRaises(TypeError, connection.get_servername, "hello")
2107
2108
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002109 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002110 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002111 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002112 immediate read.
2113 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002114 connection = Connection(Context(TLSv1_METHOD), None)
2115 self.assertEquals(connection.pending(), 0)
2116
2117
2118 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002119 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002120 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002121 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002122 connection = Connection(Context(TLSv1_METHOD), None)
2123 self.assertRaises(TypeError, connection.pending, None)
2124
2125
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002126 def test_peek(self):
2127 """
2128 :py:obj:`Connection.recv` peeks into the connection if :py:obj:`socket.MSG_PEEK` is passed.
2129 """
2130 server, client = self._loopback()
2131 server.send(b('xy'))
2132 self.assertEqual(client.recv(2, MSG_PEEK), b('xy'))
2133 self.assertEqual(client.recv(2, MSG_PEEK), b('xy'))
2134 self.assertEqual(client.recv(2), b('xy'))
2135
2136
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002137 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002138 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002139 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002140 argument or with the wrong number of arguments.
2141 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002142 connection = Connection(Context(TLSv1_METHOD), socket())
2143 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002144 self.assertRaises(TypeError, connection.connect)
2145 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002146
kjavfe508d62015-09-02 12:20:35 +01002147 def test_connection_undefined_attr(self):
2148 """
2149 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
2150 argument or with the wrong number of arguments.
2151 """
2152
2153 def attr_access_test(connection):
2154 return connection.an_attribute_which_is_not_defined
2155
2156 connection = Connection(Context(TLSv1_METHOD), None)
2157 self.assertRaises(AttributeError, attr_access_test, connection)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002158
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002159 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002160 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002161 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002162 connect method raises it.
2163 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002164 client = socket()
2165 context = Context(TLSv1_METHOD)
2166 clientSSL = Connection(context, client)
2167 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04002168 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002169
2170
2171 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002172 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002173 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002174 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002175 port = socket()
2176 port.bind(('', 0))
2177 port.listen(3)
2178
2179 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002180 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2181 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002182
2183
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002184 if platform == "darwin":
2185 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2186 else:
2187 def test_connect_ex(self):
2188 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002189 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002190 errno instead of raising an exception.
2191 """
2192 port = socket()
2193 port.bind(('', 0))
2194 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002195
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002196 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2197 clientSSL.setblocking(False)
2198 result = clientSSL.connect_ex(port.getsockname())
2199 expected = (EINPROGRESS, EWOULDBLOCK)
2200 self.assertTrue(
2201 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002202
2203
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002204 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002205 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002206 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002207 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002208 connection = Connection(Context(TLSv1_METHOD), socket())
2209 self.assertRaises(TypeError, connection.accept, None)
2210
2211
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002212 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002213 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002214 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
2215 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002216 connection originated from.
2217 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002218 ctx = Context(TLSv1_METHOD)
2219 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2220 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002221 port = socket()
2222 portSSL = Connection(ctx, port)
2223 portSSL.bind(('', 0))
2224 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002225
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002226 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002227
2228 # Calling portSSL.getsockname() here to get the server IP address sounds
2229 # great, but frequently fails on Windows.
2230 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002231
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002232 serverSSL, address = portSSL.accept()
2233
2234 self.assertTrue(isinstance(serverSSL, Connection))
2235 self.assertIdentical(serverSSL.get_context(), ctx)
2236 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002237
2238
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002239 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002240 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002241 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002242 number of arguments or with arguments other than integers.
2243 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002244 connection = Connection(Context(TLSv1_METHOD), None)
2245 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04002246 self.assertRaises(TypeError, connection.get_shutdown, None)
2247 self.assertRaises(TypeError, connection.set_shutdown)
2248 self.assertRaises(TypeError, connection.set_shutdown, None)
2249 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002250
2251
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002252 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002253 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002254 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002255 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002256 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002257 self.assertFalse(server.shutdown())
2258 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002259 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002260 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
2261 client.shutdown()
Alex Gaynor43307782015-09-04 09:05:45 -04002262 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002263 self.assertRaises(ZeroReturnError, server.recv, 1024)
Alex Gaynor43307782015-09-04 09:05:45 -04002264 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002265
2266
Paul Aurichc85e0862015-01-08 08:34:33 -08002267 def test_shutdown_closed(self):
2268 """
2269 If the underlying socket is closed, :py:obj:`Connection.shutdown` propagates the
2270 write error from the low level write call.
2271 """
2272 server, client = self._loopback()
2273 server.sock_shutdown(2)
2274 exc = self.assertRaises(SysCallError, server.shutdown)
2275 if platform == "win32":
2276 self.assertEqual(exc.args[0], ESHUTDOWN)
2277 else:
2278 self.assertEqual(exc.args[0], EPIPE)
2279
2280
Glyph89389472015-04-14 17:29:26 -04002281 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002282 """
Glyph89389472015-04-14 17:29:26 -04002283 If the underlying connection is truncated, :obj:`Connection.shutdown`
2284 raises an :obj:`Error`.
Glyph6064ec32015-04-14 16:38:22 -04002285 """
Glyph89389472015-04-14 17:29:26 -04002286 server_ctx = Context(TLSv1_METHOD)
2287 client_ctx = Context(TLSv1_METHOD)
2288 server_ctx.use_privatekey(
2289 load_privatekey(FILETYPE_PEM, server_key_pem))
2290 server_ctx.use_certificate(
2291 load_certificate(FILETYPE_PEM, server_cert_pem))
2292 server = Connection(server_ctx, None)
2293 client = Connection(client_ctx, None)
2294 self._handshakeInMemory(client, server)
2295 self.assertEqual(server.shutdown(), False)
2296 self.assertRaises(WantReadError, server.shutdown)
2297 server.bio_shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002298 self.assertRaises(Error, server.shutdown)
2299
2300
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002301 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002302 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002303 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002304 process.
2305 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002306 connection = Connection(Context(TLSv1_METHOD), socket())
2307 connection.set_shutdown(RECEIVED_SHUTDOWN)
2308 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2309
2310
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002311 if not PY3:
2312 def test_set_shutdown_long(self):
2313 """
2314 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
2315 of type :py:obj:`long` as well as :py:obj:`int`.
2316 """
2317 connection = Connection(Context(TLSv1_METHOD), socket())
2318 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
2319 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2320
2321
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002322 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002323 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002324 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
2325 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002326 with any arguments.
2327 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002328 conn = Connection(Context(TLSv1_METHOD), None)
2329 self.assertRaises(TypeError, conn.get_app_data, None)
2330 self.assertRaises(TypeError, conn.set_app_data)
2331 self.assertRaises(TypeError, conn.set_app_data, None, None)
2332
2333
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002334 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002335 """
2336 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002337 :py:obj:`Connection.set_app_data` and later retrieved with
2338 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002339 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002340 conn = Connection(Context(TLSv1_METHOD), None)
2341 app_data = object()
2342 conn.set_app_data(app_data)
2343 self.assertIdentical(conn.get_app_data(), app_data)
2344
2345
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002346 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002347 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002348 :py:obj:`Connection.makefile` is not implemented and calling that method raises
2349 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002350 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002351 conn = Connection(Context(TLSv1_METHOD), None)
2352 self.assertRaises(NotImplementedError, conn.makefile)
2353
2354
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002355 def test_get_peer_cert_chain_wrong_args(self):
2356 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002357 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002358 arguments.
2359 """
2360 conn = Connection(Context(TLSv1_METHOD), None)
2361 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
2362 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
2363 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
2364 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
2365
2366
2367 def test_get_peer_cert_chain(self):
2368 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002369 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002370 the connected server returned for the certification verification.
2371 """
2372 chain = _create_certificate_chain()
2373 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2374
2375 serverContext = Context(TLSv1_METHOD)
2376 serverContext.use_privatekey(skey)
2377 serverContext.use_certificate(scert)
2378 serverContext.add_extra_chain_cert(icert)
2379 serverContext.add_extra_chain_cert(cacert)
2380 server = Connection(serverContext, None)
2381 server.set_accept_state()
2382
2383 # Create the client
2384 clientContext = Context(TLSv1_METHOD)
2385 clientContext.set_verify(VERIFY_NONE, verify_cb)
2386 client = Connection(clientContext, None)
2387 client.set_connect_state()
2388
2389 self._interactInMemory(client, server)
2390
2391 chain = client.get_peer_cert_chain()
2392 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002393 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002394 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002395 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002396 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002397 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002398 "Authority Certificate", chain[2].get_subject().CN)
2399
2400
2401 def test_get_peer_cert_chain_none(self):
2402 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002403 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002404 certificate chain.
2405 """
2406 ctx = Context(TLSv1_METHOD)
2407 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2408 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2409 server = Connection(ctx, None)
2410 server.set_accept_state()
2411 client = Connection(Context(TLSv1_METHOD), None)
2412 client.set_connect_state()
2413 self._interactInMemory(client, server)
2414 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002415
2416
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002417 def test_get_session_wrong_args(self):
2418 """
2419 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
2420 with any arguments.
2421 """
2422 ctx = Context(TLSv1_METHOD)
2423 server = Connection(ctx, None)
2424 self.assertRaises(TypeError, server.get_session, 123)
2425 self.assertRaises(TypeError, server.get_session, "hello")
2426 self.assertRaises(TypeError, server.get_session, object())
2427
2428
2429 def test_get_session_unconnected(self):
2430 """
2431 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
2432 an object which has not been connected.
2433 """
2434 ctx = Context(TLSv1_METHOD)
2435 server = Connection(ctx, None)
2436 session = server.get_session()
2437 self.assertIdentical(None, session)
2438
2439
2440 def test_server_get_session(self):
2441 """
2442 On the server side of a connection, :py:obj:`Connection.get_session`
2443 returns a :py:class:`Session` instance representing the SSL session for
2444 that connection.
2445 """
2446 server, client = self._loopback()
2447 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002448 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002449
2450
2451 def test_client_get_session(self):
2452 """
2453 On the client side of a connection, :py:obj:`Connection.get_session`
2454 returns a :py:class:`Session` instance representing the SSL session for
2455 that connection.
2456 """
2457 server, client = self._loopback()
2458 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002459 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002460
2461
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002462 def test_set_session_wrong_args(self):
2463 """
2464 If called with an object that is not an instance of :py:class:`Session`,
2465 or with other than one argument, :py:obj:`Connection.set_session` raises
2466 :py:obj:`TypeError`.
2467 """
2468 ctx = Context(TLSv1_METHOD)
2469 connection = Connection(ctx, None)
2470 self.assertRaises(TypeError, connection.set_session)
2471 self.assertRaises(TypeError, connection.set_session, 123)
2472 self.assertRaises(TypeError, connection.set_session, "hello")
2473 self.assertRaises(TypeError, connection.set_session, object())
2474 self.assertRaises(
2475 TypeError, connection.set_session, Session(), Session())
2476
2477
2478 def test_client_set_session(self):
2479 """
2480 :py:obj:`Connection.set_session`, when used prior to a connection being
2481 established, accepts a :py:class:`Session` instance and causes an
2482 attempt to re-use the session it represents when the SSL handshake is
2483 performed.
2484 """
2485 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2486 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2487 ctx = Context(TLSv1_METHOD)
2488 ctx.use_privatekey(key)
2489 ctx.use_certificate(cert)
2490 ctx.set_session_id("unity-test")
2491
2492 def makeServer(socket):
2493 server = Connection(ctx, socket)
2494 server.set_accept_state()
2495 return server
2496
2497 originalServer, originalClient = self._loopback(
2498 serverFactory=makeServer)
2499 originalSession = originalClient.get_session()
2500
2501 def makeClient(socket):
2502 client = self._loopbackClientFactory(socket)
2503 client.set_session(originalSession)
2504 return client
2505 resumedServer, resumedClient = self._loopback(
2506 serverFactory=makeServer,
2507 clientFactory=makeClient)
2508
2509 # This is a proxy: in general, we have no access to any unique
2510 # identifier for the session (new enough versions of OpenSSL expose a
2511 # hash which could be usable, but "new enough" is very, very new).
2512 # Instead, exploit the fact that the master key is re-used if the
2513 # session is re-used. As long as the master key for the two connections
2514 # is the same, the session was re-used!
2515 self.assertEqual(
2516 originalServer.master_key(), resumedServer.master_key())
2517
2518
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002519 def test_set_session_wrong_method(self):
2520 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002521 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
2522 instance associated with a context using a different SSL method than the
2523 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
2524 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002525 """
2526 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2527 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2528 ctx = Context(TLSv1_METHOD)
2529 ctx.use_privatekey(key)
2530 ctx.use_certificate(cert)
2531 ctx.set_session_id("unity-test")
2532
2533 def makeServer(socket):
2534 server = Connection(ctx, socket)
2535 server.set_accept_state()
2536 return server
2537
2538 originalServer, originalClient = self._loopback(
2539 serverFactory=makeServer)
2540 originalSession = originalClient.get_session()
2541
2542 def makeClient(socket):
2543 # Intentionally use a different, incompatible method here.
2544 client = Connection(Context(SSLv3_METHOD), socket)
2545 client.set_connect_state()
2546 client.set_session(originalSession)
2547 return client
2548
2549 self.assertRaises(
2550 Error,
2551 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2552
2553
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002554 def test_wantWriteError(self):
2555 """
2556 :py:obj:`Connection` methods which generate output raise
2557 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2558 fail indicating a should-write state.
2559 """
2560 client_socket, server_socket = socket_pair()
2561 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002562 # anything. Only write a single byte at a time so we can be sure we
2563 # completely fill the buffer. Even though the socket API is allowed to
2564 # signal a short write via its return value it seems this doesn't
2565 # always happen on all platforms (FreeBSD and OS X particular) for the
2566 # very last bit of available buffer space.
2567 msg = b"x"
2568 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002569 try:
2570 client_socket.send(msg)
2571 except error as e:
2572 if e.errno == EWOULDBLOCK:
2573 break
2574 raise
2575 else:
2576 self.fail(
2577 "Failed to fill socket buffer, cannot test BIO want write")
2578
2579 ctx = Context(TLSv1_METHOD)
2580 conn = Connection(ctx, client_socket)
2581 # Client's speak first, so make it an SSL client
2582 conn.set_connect_state()
2583 self.assertRaises(WantWriteError, conn.do_handshake)
2584
2585 # XXX want_read
2586
Fedor Brunner416f4a12014-03-28 13:18:38 +01002587 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002588 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002589 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2590 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002591 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002592 ctx = Context(TLSv1_METHOD)
2593 connection = Connection(ctx, None)
2594 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002595
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002596
Fedor Brunner416f4a12014-03-28 13:18:38 +01002597 def test_get_peer_finished_before_connect(self):
2598 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002599 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2600 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002601 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002602 ctx = Context(TLSv1_METHOD)
2603 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002604 self.assertEqual(connection.get_peer_finished(), None)
2605
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002606
Fedor Brunner416f4a12014-03-28 13:18:38 +01002607 def test_get_finished(self):
2608 """
2609 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002610 message send from client, or server. Finished messages are send during
2611 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002612 """
2613
Fedor Brunner5747b932014-03-05 14:22:34 +01002614 server, client = self._loopback()
2615
2616 self.assertNotEqual(server.get_finished(), None)
2617 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002618
Jean-Paul Calderoned979f232014-03-30 11:58:00 -04002619
Fedor Brunner416f4a12014-03-28 13:18:38 +01002620 def test_get_peer_finished(self):
2621 """
2622 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002623 message received from client, or server. Finished messages are send
2624 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002625 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002626 server, client = self._loopback()
2627
2628 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002629 self.assertTrue(len(server.get_peer_finished()) > 0)
2630
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002631
Fedor Brunner416f4a12014-03-28 13:18:38 +01002632 def test_tls_finished_message_symmetry(self):
2633 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002634 The TLS Finished message send by server must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002635 received by client.
2636
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002637 The TLS Finished message send by client must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002638 received by server.
2639 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002640 server, client = self._loopback()
2641
Fedor Brunner5747b932014-03-05 14:22:34 +01002642 self.assertEqual(server.get_finished(), client.get_peer_finished())
2643 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002644
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002645
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002646 def test_get_cipher_name_before_connect(self):
2647 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002648 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2649 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002650 """
2651 ctx = Context(TLSv1_METHOD)
2652 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002653 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002654
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002655
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002656 def test_get_cipher_name(self):
2657 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002658 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2659 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002660 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002661 server, client = self._loopback()
2662 server_cipher_name, client_cipher_name = \
2663 server.get_cipher_name(), client.get_cipher_name()
2664
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002665 self.assertIsInstance(server_cipher_name, text_type)
2666 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002667
2668 self.assertEqual(server_cipher_name, client_cipher_name)
2669
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002670
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002671 def test_get_cipher_version_before_connect(self):
2672 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002673 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2674 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002675 """
2676 ctx = Context(TLSv1_METHOD)
2677 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002678 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002679
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002680
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002681 def test_get_cipher_version(self):
2682 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002683 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2684 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002685 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002686 server, client = self._loopback()
2687 server_cipher_version, client_cipher_version = \
2688 server.get_cipher_version(), client.get_cipher_version()
2689
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002690 self.assertIsInstance(server_cipher_version, text_type)
2691 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002692
2693 self.assertEqual(server_cipher_version, client_cipher_version)
2694
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002695
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002696 def test_get_cipher_bits_before_connect(self):
2697 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002698 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2699 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002700 """
2701 ctx = Context(TLSv1_METHOD)
2702 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002703 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002704
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002705
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002706 def test_get_cipher_bits(self):
2707 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002708 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2709 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002710 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002711 server, client = self._loopback()
2712 server_cipher_bits, client_cipher_bits = \
2713 server.get_cipher_bits(), client.get_cipher_bits()
2714
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002715 self.assertIsInstance(server_cipher_bits, int)
2716 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002717
2718 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002719
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002720
Jim Shaverabff1882015-05-27 09:15:55 -04002721 def test_get_protocol_version_name(self):
2722 """
2723 :py:obj:`Connection.get_protocol_version_name()` returns a string
2724 giving the protocol version of the current connection.
2725 """
2726 server, client = self._loopback()
2727 client_protocol_version_name = client.get_protocol_version_name()
2728 server_protocol_version_name = server.get_protocol_version_name()
2729
Jim Shaver58d25732015-05-28 11:52:32 -04002730 self.assertIsInstance(server_protocol_version_name, text_type)
2731 self.assertIsInstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002732
2733 self.assertEqual(server_protocol_version_name, client_protocol_version_name)
2734
2735
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002736 def test_get_protocol_version(self):
2737 """
Alex Gaynor43307782015-09-04 09:05:45 -04002738 :py:obj:`Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002739 giving the protocol version of the current connection.
2740 """
2741 server, client = self._loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002742 client_protocol_version = client.get_protocol_version()
2743 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002744
Jim Shaverabff1882015-05-27 09:15:55 -04002745 self.assertIsInstance(server_protocol_version, int)
2746 self.assertIsInstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002747
2748 self.assertEqual(server_protocol_version, client_protocol_version)
2749
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002750
Jim Shaver208438c2015-05-28 09:52:38 -04002751
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002752class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002753 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002754 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002755 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002756 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002757 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002758 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002759 arguments.
2760 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002761 connection = Connection(Context(TLSv1_METHOD), None)
2762 self.assertRaises(TypeError, connection.get_cipher_list, None)
2763
2764
2765 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002766 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002767 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2768 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002769 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002770 connection = Connection(Context(TLSv1_METHOD), None)
2771 ciphers = connection.get_cipher_list()
2772 self.assertTrue(isinstance(ciphers, list))
2773 for cipher in ciphers:
2774 self.assertTrue(isinstance(cipher, str))
2775
2776
2777
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002778class ConnectionSendTests(TestCase, _LoopbackMixin):
2779 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002780 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002781 """
2782 def test_wrong_args(self):
2783 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002784 When called with arguments other than string argument for its first
2785 parameter or more than two arguments, :py:obj:`Connection.send` raises
2786 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002787 """
2788 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002789 self.assertRaises(TypeError, connection.send)
2790 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002791 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002792
2793
2794 def test_short_bytes(self):
2795 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002796 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002797 and returns the number of bytes sent.
2798 """
2799 server, client = self._loopback()
2800 count = server.send(b('xy'))
2801 self.assertEquals(count, 2)
2802 self.assertEquals(client.recv(2), b('xy'))
2803
Abraham Martinef063482015-03-25 14:06:24 +00002804
2805 def test_text(self):
2806 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002807 When passed a text, :py:obj:`Connection.send` transmits all of it and
2808 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002809 """
2810 server, client = self._loopback()
2811 with catch_warnings(record=True) as w:
2812 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002813 count = server.send(b"xy".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002814 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002815 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002816 WARNING_TYPE_EXPECTED
2817 ),
2818 str(w[-1].message)
2819 )
2820 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinef063482015-03-25 14:06:24 +00002821 self.assertEquals(count, 2)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002822 self.assertEquals(client.recv(2), b"xy")
Abraham Martinef063482015-03-25 14:06:24 +00002823
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002824 try:
2825 memoryview
2826 except NameError:
2827 "cannot test sending memoryview without memoryview"
2828 else:
2829 def test_short_memoryview(self):
2830 """
2831 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002832 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002833 bytes sent.
2834 """
2835 server, client = self._loopback()
2836 count = server.send(memoryview(b('xy')))
2837 self.assertEquals(count, 2)
2838 self.assertEquals(client.recv(2), b('xy'))
2839
2840
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002841 try:
2842 buffer
2843 except NameError:
2844 "cannot test sending buffer without buffer"
2845 else:
2846 def test_short_buffer(self):
2847 """
2848 When passed a buffer containing a small number of bytes,
2849 :py:obj:`Connection.send` transmits all of them and returns the number of
2850 bytes sent.
2851 """
2852 server, client = self._loopback()
2853 count = server.send(buffer(b('xy')))
2854 self.assertEquals(count, 2)
2855 self.assertEquals(client.recv(2), b('xy'))
2856
2857
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002858
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002859def _make_memoryview(size):
2860 """
2861 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2862 size.
2863 """
2864 return memoryview(bytearray(size))
2865
2866
2867
Cory Benfield62d10332014-06-15 10:03:41 +01002868class ConnectionRecvIntoTests(TestCase, _LoopbackMixin):
2869 """
2870 Tests for :py:obj:`Connection.recv_into`
2871 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002872 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002873 """
2874 Assert that when the given buffer is passed to
2875 ``Connection.recv_into``, whatever bytes are available to be received
2876 that fit into that buffer are written into that buffer.
2877 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002878 output_buffer = factory(5)
2879
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002880 server, client = self._loopback()
2881 server.send(b('xy'))
2882
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002883 self.assertEqual(client.recv_into(output_buffer), 2)
2884 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002885
2886
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002887 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002888 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002889 :py:obj:`Connection.recv_into` can be passed a ``bytearray`` instance
2890 and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002891 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002892 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002893
2894
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002895 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002896 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002897 Assert that when the given buffer is passed to ``Connection.recv_into``
2898 along with a value for ``nbytes`` that is less than the size of that
2899 buffer, only ``nbytes`` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002900 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002901 output_buffer = factory(10)
2902
Cory Benfield62d10332014-06-15 10:03:41 +01002903 server, client = self._loopback()
2904 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002905
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002906 self.assertEqual(client.recv_into(output_buffer, 5), 5)
2907 self.assertEqual(
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002908 output_buffer, bytearray(b('abcde\x00\x00\x00\x00\x00'))
2909 )
2910
2911
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002912 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002913 """
2914 When called with a ``bytearray`` instance,
2915 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter and
2916 doesn't copy in more than that number of bytes.
2917 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002918 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002919
2920
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002921 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002922 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002923 Assert that if there are more bytes available to be read from the
2924 receive buffer than would fit into the buffer passed to
2925 :py:obj:`Connection.recv_into`, only as many as fit are written into
2926 it.
Cory Benfield62d10332014-06-15 10:03:41 +01002927 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002928 output_buffer = factory(5)
2929
Cory Benfield62d10332014-06-15 10:03:41 +01002930 server, client = self._loopback()
2931 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002932
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002933 self.assertEqual(client.recv_into(output_buffer), 5)
2934 self.assertEqual(output_buffer, bytearray(b('abcde')))
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002935 rest = client.recv(5)
2936 self.assertEqual(b('fghij'), rest)
2937
2938
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002939 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002940 """
2941 When called with a ``bytearray`` instance,
2942 :py:obj:`Connection.recv_into` respects the size of the array and
2943 doesn't write more bytes into it than will fit.
2944 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002945 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002946
2947
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002948 def _really_doesnt_overfill_test(self, factory):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002949 """
2950 Assert that if the value given by ``nbytes`` is greater than the actual
2951 size of the output buffer passed to :py:obj:`Connection.recv_into`, the
2952 behavior is as if no value was given for ``nbytes`` at all.
2953 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002954 output_buffer = factory(5)
2955
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002956 server, client = self._loopback()
2957 server.send(b('abcdefghij'))
2958
2959 self.assertEqual(client.recv_into(output_buffer, 50), 5)
2960 self.assertEqual(output_buffer, bytearray(b('abcde')))
2961 rest = client.recv(5)
2962 self.assertEqual(b('fghij'), rest)
2963
2964
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002965 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002966 """
2967 When called with a ``bytearray`` instance and an ``nbytes`` value that
2968 is too large, :py:obj:`Connection.recv_into` respects the size of the
2969 array and not the ``nbytes`` value and doesn't write more bytes into
2970 the buffer than will fit.
2971 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002972 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002973
2974
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002975 def test_peek(self):
2976
2977 server, client = self._loopback()
2978 server.send(b('xy'))
2979
2980 for _ in range(2):
2981 output_buffer = bytearray(5)
2982 self.assertEqual(client.recv_into(output_buffer, flags=MSG_PEEK), 2)
2983 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
2984
2985
Cory Benfield62d10332014-06-15 10:03:41 +01002986 try:
2987 memoryview
2988 except NameError:
2989 "cannot test recv_into memoryview without memoryview"
2990 else:
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002991 def test_memoryview_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002992 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002993 :py:obj:`Connection.recv_into` can be passed a ``memoryview``
2994 instance and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002995 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002996 self._no_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002997
2998
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002999 def test_memoryview_respects_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01003000 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003001 When called with a ``memoryview`` instance,
3002 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter
3003 and doesn't copy more than that number of bytes in.
Cory Benfield62d10332014-06-15 10:03:41 +01003004 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003005 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003006
3007
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003008 def test_memoryview_doesnt_overfill(self):
Cory Benfield62d10332014-06-15 10:03:41 +01003009 """
Jean-Paul Calderone8fd82552015-03-15 17:21:07 -04003010 When called with a ``memoryview`` instance,
3011 :py:obj:`Connection.recv_into` respects the size of the array and
3012 doesn't write more bytes into it than will fit.
Cory Benfield62d10332014-06-15 10:03:41 +01003013 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003014 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003015
3016
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003017 def test_memoryview_really_doesnt_overfill(self):
3018 """
3019 When called with a ``memoryview`` instance and an ``nbytes`` value
3020 that is too large, :py:obj:`Connection.recv_into` respects the size
3021 of the array and not the ``nbytes`` value and doesn't write more
3022 bytes into the buffer than will fit.
3023 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003024 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003025
3026
Cory Benfield62d10332014-06-15 10:03:41 +01003027
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003028class ConnectionSendallTests(TestCase, _LoopbackMixin):
3029 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003030 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003031 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003032 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003033 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003034 When called with arguments other than a string argument for its first
3035 parameter or with more than two arguments, :py:obj:`Connection.sendall`
3036 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003037 """
3038 connection = Connection(Context(TLSv1_METHOD), None)
3039 self.assertRaises(TypeError, connection.sendall)
3040 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003041 self.assertRaises(
3042 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003043
3044
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003045 def test_short(self):
3046 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003047 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003048 it.
3049 """
3050 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04003051 server.sendall(b('x'))
3052 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003053
3054
Abraham Martinef063482015-03-25 14:06:24 +00003055 def test_text(self):
3056 """
Jean-Paul Calderone93477422015-04-13 20:38:57 -04003057 :py:obj:`Connection.sendall` transmits all the content in the string
3058 passed to it raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003059 """
3060 server, client = self._loopback()
3061 with catch_warnings(record=True) as w:
3062 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003063 server.sendall(b"x".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003064 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003065 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003066 WARNING_TYPE_EXPECTED
3067 ),
3068 str(w[-1].message)
3069 )
3070 self.assertIs(w[-1].category, DeprecationWarning)
3071 self.assertEquals(client.recv(1), b"x")
Abraham Martinef063482015-03-25 14:06:24 +00003072
3073
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003074 try:
3075 memoryview
3076 except NameError:
3077 "cannot test sending memoryview without memoryview"
3078 else:
3079 def test_short_memoryview(self):
3080 """
3081 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003082 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003083 """
3084 server, client = self._loopback()
3085 server.sendall(memoryview(b('x')))
3086 self.assertEquals(client.recv(1), b('x'))
3087
3088
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003089 try:
3090 buffer
3091 except NameError:
3092 "cannot test sending buffers without buffers"
3093 else:
3094 def test_short_buffers(self):
3095 """
3096 When passed a buffer containing a small number of bytes,
3097 :py:obj:`Connection.sendall` transmits all of them.
3098 """
3099 server, client = self._loopback()
3100 server.sendall(buffer(b('x')))
3101 self.assertEquals(client.recv(1), b('x'))
3102
3103
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003104 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003105 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003106 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003107 it even if this requires multiple calls of an underlying write function.
3108 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003109 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003110 # Should be enough, underlying SSL_write should only do 16k at a time.
3111 # On Windows, after 32k of bytes the write will block (forever - because
3112 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04003113 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003114 server.sendall(message)
3115 accum = []
3116 received = 0
3117 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003118 data = client.recv(1024)
3119 accum.append(data)
3120 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04003121 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003122
3123
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003124 def test_closed(self):
3125 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003126 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003127 write error from the low level write call.
3128 """
3129 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003130 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003131 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003132 if platform == "win32":
3133 self.assertEqual(exc.args[0], ESHUTDOWN)
3134 else:
3135 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003136
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003137
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04003138
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003139class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
3140 """
3141 Tests for SSL renegotiation APIs.
3142 """
3143 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003144 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003145 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003146 arguments.
3147 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003148 connection = Connection(Context(TLSv1_METHOD), None)
3149 self.assertRaises(TypeError, connection.renegotiate, None)
3150
3151
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003152 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003153 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003154 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003155 any arguments.
3156 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003157 connection = Connection(Context(TLSv1_METHOD), None)
3158 self.assertRaises(TypeError, connection.total_renegotiations, None)
3159
3160
3161 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003162 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003163 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003164 renegotiations have happened.
3165 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003166 connection = Connection(Context(TLSv1_METHOD), None)
3167 self.assertEquals(connection.total_renegotiations(), 0)
3168
3169
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003170# def test_renegotiate(self):
3171# """
3172# """
3173# server, client = self._loopback()
3174
3175# server.send("hello world")
3176# self.assertEquals(client.recv(len("hello world")), "hello world")
3177
3178# self.assertEquals(server.total_renegotiations(), 0)
3179# self.assertTrue(server.renegotiate())
3180
3181# server.setblocking(False)
3182# client.setblocking(False)
3183# while server.renegotiate_pending():
3184# client.do_handshake()
3185# server.do_handshake()
3186
3187# self.assertEquals(server.total_renegotiations(), 1)
3188
3189
3190
3191
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003192class ErrorTests(TestCase):
3193 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003194 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003195 """
3196 def test_type(self):
3197 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003198 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003199 """
3200 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05003201 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05003202
3203
3204
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003205class ConstantsTests(TestCase):
3206 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003207 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003208
3209 These are values defined by OpenSSL intended only to be used as flags to
3210 OpenSSL APIs. The only assertions it seems can be made about them is
3211 their values.
3212 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003213 # unittest.TestCase has no skip mechanism
3214 if OP_NO_QUERY_MTU is not None:
3215 def test_op_no_query_mtu(self):
3216 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003217 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003218 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003219 """
3220 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
3221 else:
3222 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003223
3224
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003225 if OP_COOKIE_EXCHANGE is not None:
3226 def test_op_cookie_exchange(self):
3227 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003228 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003229 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003230 """
3231 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
3232 else:
3233 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003234
3235
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003236 if OP_NO_TICKET is not None:
3237 def test_op_no_ticket(self):
3238 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003239 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003240 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003241 """
3242 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04003243 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003244 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05003245
3246
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003247 if OP_NO_COMPRESSION is not None:
3248 def test_op_no_compression(self):
3249 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003250 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
3251 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003252 """
3253 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
3254 else:
3255 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3256
3257
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003258 def test_sess_cache_off(self):
3259 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003260 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3261 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003262 """
3263 self.assertEqual(0x0, SESS_CACHE_OFF)
3264
3265
3266 def test_sess_cache_client(self):
3267 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003268 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3269 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003270 """
3271 self.assertEqual(0x1, SESS_CACHE_CLIENT)
3272
3273
3274 def test_sess_cache_server(self):
3275 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003276 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3277 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003278 """
3279 self.assertEqual(0x2, SESS_CACHE_SERVER)
3280
3281
3282 def test_sess_cache_both(self):
3283 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003284 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3285 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003286 """
3287 self.assertEqual(0x3, SESS_CACHE_BOTH)
3288
3289
3290 def test_sess_cache_no_auto_clear(self):
3291 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003292 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3293 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3294 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003295 """
3296 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
3297
3298
3299 def test_sess_cache_no_internal_lookup(self):
3300 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003301 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3302 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3303 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003304 """
3305 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
3306
3307
3308 def test_sess_cache_no_internal_store(self):
3309 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003310 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3311 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3312 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003313 """
3314 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
3315
3316
3317 def test_sess_cache_no_internal(self):
3318 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003319 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3320 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
3321 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003322 """
3323 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
3324
3325
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04003326
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003327class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05003328 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003329 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003330 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003331 def _server(self, sock):
3332 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003333 Create a new server-side SSL :py:obj:`Connection` object wrapped around
3334 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003335 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003336 # Create the server side Connection. This is mostly setup boilerplate
3337 # - use TLSv1, use a particular certificate, etc.
3338 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003339 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
3340 server_ctx.set_verify(VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE, verify_cb)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003341 server_store = server_ctx.get_cert_store()
3342 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3343 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3344 server_ctx.check_privatekey()
3345 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003346 # Here the Connection is actually created. If None is passed as the 2nd
3347 # parameter, it indicates a memory BIO should be created.
3348 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003349 server_conn.set_accept_state()
3350 return server_conn
3351
3352
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003353 def _client(self, sock):
3354 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003355 Create a new client-side SSL :py:obj:`Connection` object wrapped around
3356 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003357 """
3358 # Now create the client side Connection. Similar boilerplate to the
3359 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003360 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003361 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
3362 client_ctx.set_verify(VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE, verify_cb)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003363 client_store = client_ctx.get_cert_store()
3364 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
3365 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
3366 client_ctx.check_privatekey()
3367 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003368 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003369 client_conn.set_connect_state()
3370 return client_conn
3371
3372
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003373 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003374 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003375 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003376 reading from the output of each and writing those bytes to the input of
3377 the other and in this way establish a connection and exchange
3378 application-level bytes with each other.
3379 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003380 server_conn = self._server(None)
3381 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003382
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003383 # There should be no key or nonces yet.
3384 self.assertIdentical(server_conn.master_key(), None)
3385 self.assertIdentical(server_conn.client_random(), None)
3386 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003387
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003388 # First, the handshake needs to happen. We'll deliver bytes back and
3389 # forth between the client and server until neither of them feels like
3390 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003391 self.assertIdentical(
3392 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003393
3394 # Now that the handshake is done, there should be a key and nonces.
3395 self.assertNotIdentical(server_conn.master_key(), None)
3396 self.assertNotIdentical(server_conn.client_random(), None)
3397 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04003398 self.assertEquals(server_conn.client_random(), client_conn.client_random())
3399 self.assertEquals(server_conn.server_random(), client_conn.server_random())
3400 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
3401 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003402
3403 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003404 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05003405
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003406 server_conn.write(important_message)
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 (client_conn, important_message))
3410
3411 client_conn.write(important_message[::-1])
3412 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003413 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003414 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003415
3416
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003417 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003418 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003419 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003420
3421 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09003422 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003423 this test fails, there must be a problem outside the memory BIO
3424 code, as no memory BIO is involved here). Even though this isn't a
3425 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003426 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04003427 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003428
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003429 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05003430 client_conn.send(important_message)
3431 msg = server_conn.recv(1024)
3432 self.assertEqual(msg, important_message)
3433
3434 # Again in the other direction, just for fun.
3435 important_message = important_message[::-1]
3436 server_conn.send(important_message)
3437 msg = client_conn.recv(1024)
3438 self.assertEqual(msg, important_message)
3439
3440
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04003441 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003442 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003443 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
3444 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003445 """
3446 context = Context(SSLv3_METHOD)
3447 client = socket()
3448 clientSSL = Connection(context, client)
Alex Gaynor43307782015-09-04 09:05:45 -04003449 self.assertRaises(TypeError, clientSSL.bio_read, 100)
3450 self.assertRaises(TypeError, clientSSL.bio_write, "foo")
Alex Gaynor7e8b61e2015-09-04 13:13:05 -04003451 self.assertRaises(TypeError, clientSSL.bio_shutdown)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003452
3453
3454 def test_outgoingOverflow(self):
3455 """
3456 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09003457 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003458 returned and that many bytes from the beginning of the input can be
3459 read from the other end of the connection.
3460 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003461 server = self._server(None)
3462 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003463
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003464 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003465
3466 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003467 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003468 # Sanity check. We're trying to test what happens when the entire
3469 # input can't be sent. If the entire input was sent, this test is
3470 # meaningless.
3471 self.assertTrue(sent < size)
3472
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003473 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003474 self.assertIdentical(receiver, server)
3475
3476 # We can rely on all of these bytes being received at once because
3477 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
3478 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003479
3480
3481 def test_shutdown(self):
3482 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003483 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
3484 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003485 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003486 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003487 server.bio_shutdown()
3488 e = self.assertRaises(Error, server.recv, 1024)
3489 # We don't want WantReadError or ZeroReturnError or anything - it's a
3490 # handshake failure.
3491 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003492
3493
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003494 def test_unexpectedEndOfFile(self):
3495 """
3496 If the connection is lost before an orderly SSL shutdown occurs,
3497 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
3498 "Unexpected EOF".
3499 """
3500 server_conn, client_conn = self._loopback()
3501 client_conn.sock_shutdown(SHUT_RDWR)
3502 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
3503 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
3504
3505
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003506 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003507 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003508 Verify the return value of the :py:obj:`get_client_ca_list` method for server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003509
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003510 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003511 before the client and server are connected to each other. This
3512 function should specify a list of CAs for the server to send to the
3513 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09003514 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003515 times.
3516 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003517 server = self._server(None)
3518 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003519 self.assertEqual(client.get_client_ca_list(), [])
3520 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003521 ctx = server.get_context()
3522 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003523 self.assertEqual(client.get_client_ca_list(), [])
3524 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003525 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003526 self.assertEqual(client.get_client_ca_list(), expected)
3527 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003528
3529
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003530 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003531 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003532 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003533 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003534 """
3535 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003536 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
3537 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
3538 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003539
3540
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003541 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003542 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003543 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003544 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09003545 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003546 after the connection is set up.
3547 """
3548 def no_ca(ctx):
3549 ctx.set_client_ca_list([])
3550 return []
3551 self._check_client_ca_list(no_ca)
3552
3553
3554 def test_set_one_ca_list(self):
3555 """
3556 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003557 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003558 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003559 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003560 X509Name after the connection is set up.
3561 """
3562 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3563 cadesc = cacert.get_subject()
3564 def single_ca(ctx):
3565 ctx.set_client_ca_list([cadesc])
3566 return [cadesc]
3567 self._check_client_ca_list(single_ca)
3568
3569
3570 def test_set_multiple_ca_list(self):
3571 """
3572 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003573 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003574 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003575 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003576 X509Names after the connection is set up.
3577 """
3578 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3579 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3580
3581 sedesc = secert.get_subject()
3582 cldesc = clcert.get_subject()
3583
3584 def multiple_ca(ctx):
3585 L = [sedesc, cldesc]
3586 ctx.set_client_ca_list(L)
3587 return L
3588 self._check_client_ca_list(multiple_ca)
3589
3590
3591 def test_reset_ca_list(self):
3592 """
3593 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09003594 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003595 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003596 """
3597 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3598 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3599 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3600
3601 cadesc = cacert.get_subject()
3602 sedesc = secert.get_subject()
3603 cldesc = clcert.get_subject()
3604
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003605 def changed_ca(ctx):
3606 ctx.set_client_ca_list([sedesc, cldesc])
3607 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003608 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003609 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003610
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003611
3612 def test_mutated_ca_list(self):
3613 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003614 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003615 afterwards, this does not affect the list of CA names sent to the
3616 client.
3617 """
3618 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3619 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3620
3621 cadesc = cacert.get_subject()
3622 sedesc = secert.get_subject()
3623
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003624 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003625 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003626 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003627 L.append(sedesc)
3628 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003629 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003630
3631
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003632 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003633 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003634 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003635 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003636 """
3637 ctx = Context(TLSv1_METHOD)
3638 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003639 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003640 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003641 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003642
3643
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003644 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003645 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003646 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09003647 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003648 """
3649 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3650 cadesc = cacert.get_subject()
3651 def single_ca(ctx):
3652 ctx.add_client_ca(cacert)
3653 return [cadesc]
3654 self._check_client_ca_list(single_ca)
3655
3656
3657 def test_multiple_add_client_ca(self):
3658 """
3659 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09003660 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003661 """
3662 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3663 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3664
3665 cadesc = cacert.get_subject()
3666 sedesc = secert.get_subject()
3667
3668 def multiple_ca(ctx):
3669 ctx.add_client_ca(cacert)
3670 ctx.add_client_ca(secert)
3671 return [cadesc, sedesc]
3672 self._check_client_ca_list(multiple_ca)
3673
3674
3675 def test_set_and_add_client_ca(self):
3676 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003677 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
3678 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003679 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003680 """
3681 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3682 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3683 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3684
3685 cadesc = cacert.get_subject()
3686 sedesc = secert.get_subject()
3687 cldesc = clcert.get_subject()
3688
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003689 def mixed_set_add_ca(ctx):
3690 ctx.set_client_ca_list([cadesc, sedesc])
3691 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003692 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003693 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003694
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003695
3696 def test_set_after_add_client_ca(self):
3697 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003698 A call to :py:obj:`Context.set_client_ca_list` after a call to
3699 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003700 call with the names specified by the latter cal.
3701 """
3702 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3703 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3704 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3705
3706 cadesc = cacert.get_subject()
3707 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003708
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003709 def set_replaces_add_ca(ctx):
3710 ctx.add_client_ca(clcert)
3711 ctx.set_client_ca_list([cadesc])
3712 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003713 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003714 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003715
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003716
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003717
3718class ConnectionBIOTests(TestCase):
3719 """
3720 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3721 """
3722 def test_wantReadError(self):
3723 """
3724 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
3725 if there are no bytes available to be read from the BIO.
3726 """
3727 ctx = Context(TLSv1_METHOD)
3728 conn = Connection(ctx, None)
3729 self.assertRaises(WantReadError, conn.bio_read, 1024)
3730
3731
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003732 def test_buffer_size(self):
3733 """
3734 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3735 number of bytes to read and return.
3736 """
3737 ctx = Context(TLSv1_METHOD)
3738 conn = Connection(ctx, None)
3739 conn.set_connect_state()
3740 try:
3741 conn.do_handshake()
3742 except WantReadError:
3743 pass
3744 data = conn.bio_read(2)
3745 self.assertEqual(2, len(data))
3746
3747
3748 if not PY3:
3749 def test_buffer_size_long(self):
3750 """
3751 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3752 :py:obj:`long` as well as :py:obj:`int`.
3753 """
3754 ctx = Context(TLSv1_METHOD)
3755 conn = Connection(ctx, None)
3756 conn.set_connect_state()
3757 try:
3758 conn.do_handshake()
3759 except WantReadError:
3760 pass
3761 data = conn.bio_read(long(2))
3762 self.assertEqual(2, len(data))
3763
3764
3765
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003766
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003767class InfoConstantTests(TestCase):
3768 """
3769 Tests for assorted constants exposed for use in info callbacks.
3770 """
3771 def test_integers(self):
3772 """
3773 All of the info constants are integers.
3774
3775 This is a very weak test. It would be nice to have one that actually
3776 verifies that as certain info events happen, the value passed to the
3777 info callback matches up with the constant exposed by OpenSSL.SSL.
3778 """
3779 for const in [
3780 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3781 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3782 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3783 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3784 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
3785 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
3786
3787 self.assertTrue(isinstance(const, int))
3788
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003789
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003790if __name__ == '__main__':
3791 main()