blob: b104a098e18cc7c31b9d164e2ac134c90106988a [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
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070011from socket import 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
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040090# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
91# to use)
92dhparam = """\
93-----BEGIN DH PARAMETERS-----
94MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
95-----END DH PARAMETERS-----
96"""
97
98
Jean-Paul Calderone05826732015-04-12 11:38:49 -040099def join_bytes_or_unicode(prefix, suffix):
100 """
101 Join two path components of either ``bytes`` or ``unicode``.
102
103 The return type is the same as the type of ``prefix``.
104 """
105 # If the types are the same, nothing special is necessary.
106 if type(prefix) == type(suffix):
107 return join(prefix, suffix)
108
109 # Otherwise, coerce suffix to the type of prefix.
110 if isinstance(prefix, text_type):
111 return join(prefix, suffix.decode(getfilesystemencoding()))
112 else:
113 return join(prefix, suffix.encode(getfilesystemencoding()))
114
115
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400116def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400117 return ok
118
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400119
Rick Deanb1ccd562009-07-09 23:52:39 -0500120def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400121 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400122 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400123 """
124 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500125 port = socket()
126 port.bind(('', 0))
127 port.listen(1)
128 client = socket()
129 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400130 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400131 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500132 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500133
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400134 # Let's pass some unencrypted data to make sure our socket connection is
135 # fine. Just one byte, so we don't have to worry about buffers getting
136 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400137 server.send(b("x"))
138 assert client.recv(1024) == b("x")
139 client.send(b("y"))
140 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500141
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400142 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400143 server.setblocking(False)
144 client.setblocking(False)
145
Rick Deanb1ccd562009-07-09 23:52:39 -0500146 return (server, client)
147
148
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400149
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([
208 X509Extension(b('basicConstraints'), True, b('CA:false'))])
209 scert.set_serial_number(0)
210 scert.sign(ikey, "sha1")
211
212 return [(cakey, cacert), (ikey, icert), (skey, scert)]
213
214
215
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400216class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400217 """
218 Helper mixin which defines methods for creating a connected socket pair and
219 for forcing two connected SSL sockets to talk to each other via memory BIOs.
220 """
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
227 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400228 ctx = Context(TLSv1_METHOD)
229 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
230 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500231 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400232 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500233 return server
234
235
236 def _loopback(self, serverFactory=None, clientFactory=None):
237 if serverFactory is None:
238 serverFactory = self._loopbackServerFactory
239 if clientFactory is None:
240 clientFactory = self._loopbackClientFactory
241
242 (server, client) = socket_pair()
243 server = serverFactory(server)
244 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400245
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400246 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400247
248 server.setblocking(True)
249 client.setblocking(True)
250 return server, client
251
252
253 def _interactInMemory(self, client_conn, server_conn):
254 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900255 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400256 objects. Copy bytes back and forth between their send/receive buffers
257 for as long as there is anything to copy. When there is nothing more
Jonathan Ballet648875f2011-07-16 14:14:58 +0900258 to copy, return :py:obj:`None`. If one of them actually manages to deliver
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400259 some application bytes, return a two-tuple of the connection from which
260 the bytes were read and the bytes themselves.
261 """
262 wrote = True
263 while wrote:
264 # Loop until neither side has anything to say
265 wrote = False
266
267 # Copy stuff from each side's send buffer to the other side's
268 # receive buffer.
269 for (read, write) in [(client_conn, server_conn),
270 (server_conn, client_conn)]:
271
272 # Give the side a chance to generate some more bytes, or
273 # succeed.
274 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400275 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400276 except WantReadError:
277 # It didn't succeed, so we'll hope it generated some
278 # output.
279 pass
280 else:
281 # It did succeed, so we'll stop now and let the caller deal
282 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400283 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400284
285 while True:
286 # Keep copying as long as there's more stuff there.
287 try:
288 dirty = read.bio_read(4096)
289 except WantReadError:
290 # Okay, nothing more waiting to be sent. Stop
291 # processing this send buffer.
292 break
293 else:
294 # Keep track of the fact that someone generated some
295 # output.
296 wrote = True
297 write.bio_write(dirty)
298
299
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400300 def _handshakeInMemory(self, client_conn, server_conn):
Jean-Paul Calderoneb2b40782014-05-06 08:47:40 -0400301 """
302 Perform the TLS handshake between two :py:class:`Connection` instances
303 connected to each other via memory BIOs.
304 """
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400305 client_conn.set_connect_state()
306 server_conn.set_accept_state()
307
308 for conn in [client_conn, server_conn]:
309 try:
310 conn.do_handshake()
311 except WantReadError:
312 pass
313
314 self._interactInMemory(client_conn, server_conn)
315
316
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400317
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400318class VersionTests(TestCase):
319 """
320 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900321 :py:obj:`OpenSSL.SSL.SSLeay_version` and
322 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400323 """
324 def test_OPENSSL_VERSION_NUMBER(self):
325 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900326 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400327 byte and the patch, fix, minor, and major versions in the
328 nibbles above that.
329 """
330 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
331
332
333 def test_SSLeay_version(self):
334 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900335 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400336 one of a number of version strings based on that indicator.
337 """
338 versions = {}
339 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
340 SSLEAY_PLATFORM, SSLEAY_DIR]:
341 version = SSLeay_version(t)
342 versions[version] = t
343 self.assertTrue(isinstance(version, bytes))
344 self.assertEqual(len(versions), 5)
345
346
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400347
348class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400349 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900350 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400351 """
352 def test_method(self):
353 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900354 :py:obj:`Context` can be instantiated with one of :py:obj:`SSLv2_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400355 :py:obj:`SSLv3_METHOD`, :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
356 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400357 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400358 methods = [
359 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
360 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400361 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400362
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400363
364 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
365 for meth in maybe:
366 try:
367 Context(meth)
368 except (Error, ValueError):
369 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
370 # don't. Difficult to say in advance.
371 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400372
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400373 self.assertRaises(TypeError, Context, "")
374 self.assertRaises(ValueError, Context, 10)
375
376
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500377 if not PY3:
378 def test_method_long(self):
379 """
380 On Python 2 :py:class:`Context` accepts values of type
381 :py:obj:`long` as well as :py:obj:`int`.
382 """
383 Context(long(TLSv1_METHOD))
384
385
386
Rick Deane15b1472009-07-09 15:53:42 -0500387 def test_type(self):
388 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900389 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400390 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500391 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400392 self.assertIdentical(Context, ContextType)
393 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500394
395
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400396 def test_use_privatekey(self):
397 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900398 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400399 """
400 key = PKey()
401 key.generate_key(TYPE_RSA, 128)
402 ctx = Context(TLSv1_METHOD)
403 ctx.use_privatekey(key)
404 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400405
406
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800407 def test_use_privatekey_file_missing(self):
408 """
409 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error`
410 when passed the name of a file which does not exist.
411 """
412 ctx = Context(TLSv1_METHOD)
413 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
414
415
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400416 def _use_privatekey_file_test(self, pemfile, filetype):
417 """
418 Verify that calling ``Context.use_privatekey_file`` with the given
419 arguments does not raise an exception.
420 """
421 key = PKey()
422 key.generate_key(TYPE_RSA, 128)
423
424 with open(pemfile, "wt") as pem:
425 pem.write(
426 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
427 )
428
429 ctx = Context(TLSv1_METHOD)
430 ctx.use_privatekey_file(pemfile, filetype)
431
432
433 def test_use_privatekey_file_bytes(self):
434 """
435 A private key can be specified from a file by passing a ``bytes``
436 instance giving the file name to ``Context.use_privatekey_file``.
437 """
438 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400439 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400440 FILETYPE_PEM,
441 )
442
443
444 def test_use_privatekey_file_unicode(self):
445 """
446 A private key can be specified from a file by passing a ``unicode``
447 instance giving the file name to ``Context.use_privatekey_file``.
448 """
449 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400450 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400451 FILETYPE_PEM,
452 )
453
454
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500455 if not PY3:
456 def test_use_privatekey_file_long(self):
457 """
458 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
459 filetype of type :py:obj:`long` as well as :py:obj:`int`.
460 """
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400461 self._use_privatekey_file_test(self.mktemp(), long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500462
463
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800464 def test_use_certificate_wrong_args(self):
465 """
466 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
467 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as an
468 argument.
469 """
470 ctx = Context(TLSv1_METHOD)
471 self.assertRaises(TypeError, ctx.use_certificate)
472 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
473 self.assertRaises(TypeError, ctx.use_certificate, X509(), "hello, world")
474
475
476 def test_use_certificate_uninitialized(self):
477 """
478 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
479 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
480 initialized (ie, which does not actually have any certificate data).
481 """
482 ctx = Context(TLSv1_METHOD)
483 self.assertRaises(Error, ctx.use_certificate, X509())
484
485
486 def test_use_certificate(self):
487 """
488 :py:obj:`Context.use_certificate` sets the certificate which will be
489 used to identify connections created using the context.
490 """
491 # TODO
492 # Hard to assert anything. But we could set a privatekey then ask
493 # OpenSSL if the cert and key agree using check_privatekey. Then as
494 # long as check_privatekey works right we're good...
495 ctx = Context(TLSv1_METHOD)
496 ctx.use_certificate(load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
497
498
499 def test_use_certificate_file_wrong_args(self):
500 """
501 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
502 called with zero arguments or more than two arguments, or if the first
503 argument is not a byte string or the second argumnent is not an integer.
504 """
505 ctx = Context(TLSv1_METHOD)
506 self.assertRaises(TypeError, ctx.use_certificate_file)
507 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile", object())
508 self.assertRaises(
509 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM, object())
510 self.assertRaises(
511 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
512 self.assertRaises(
513 TypeError, ctx.use_certificate_file, b"somefile", object())
514
515
516 def test_use_certificate_file_missing(self):
517 """
518 :py:obj:`Context.use_certificate_file` raises
519 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does not
520 exist.
521 """
522 ctx = Context(TLSv1_METHOD)
523 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
524
525
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400526 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800527 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400528 Verify that calling ``Context.use_certificate_file`` with the given
529 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800530 """
531 # TODO
532 # Hard to assert anything. But we could set a privatekey then ask
533 # OpenSSL if the cert and key agree using check_privatekey. Then as
534 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400535 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800536 pem_file.write(cleartextCertificatePEM)
537
538 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400539 ctx.use_certificate_file(certificate_file)
540
541
542 def test_use_certificate_file_bytes(self):
543 """
544 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
545 ``bytes`` filename) which will be used to identify connections created
546 using the context.
547 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400548 filename = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400549 self._use_certificate_file_test(filename)
550
551
552 def test_use_certificate_file_unicode(self):
553 """
554 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
555 ``bytes`` filename) which will be used to identify connections created
556 using the context.
557 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400558 filename = self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400559 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800560
561
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500562 if not PY3:
563 def test_use_certificate_file_long(self):
564 """
565 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
566 filetype of type :py:obj:`long` as well as :py:obj:`int`.
567 """
568 pem_filename = self.mktemp()
569 with open(pem_filename, "wb") as pem_file:
570 pem_file.write(cleartextCertificatePEM)
571
572 ctx = Context(TLSv1_METHOD)
573 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
574
575
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500576 def test_check_privatekey_valid(self):
577 """
578 :py:obj:`Context.check_privatekey` returns :py:obj:`None` if the
579 :py:obj:`Context` instance has been configured to use a matched key and
580 certificate pair.
581 """
582 key = load_privatekey(FILETYPE_PEM, client_key_pem)
583 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
584 context = Context(TLSv1_METHOD)
585 context.use_privatekey(key)
586 context.use_certificate(cert)
587 self.assertIs(None, context.check_privatekey())
588
589
590 def test_check_privatekey_invalid(self):
591 """
592 :py:obj:`Context.check_privatekey` raises :py:obj:`Error` if the
593 :py:obj:`Context` instance has been configured to use a key and
594 certificate pair which don't relate to each other.
595 """
596 key = load_privatekey(FILETYPE_PEM, client_key_pem)
597 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
598 context = Context(TLSv1_METHOD)
599 context.use_privatekey(key)
600 context.use_certificate(cert)
601 self.assertRaises(Error, context.check_privatekey)
602
603
604 def test_check_privatekey_wrong_args(self):
605 """
606 :py:obj:`Context.check_privatekey` raises :py:obj:`TypeError` if called
607 with other than no arguments.
608 """
609 context = Context(TLSv1_METHOD)
610 self.assertRaises(TypeError, context.check_privatekey, object())
611
612
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400613 def test_set_app_data_wrong_args(self):
614 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900615 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called with other than
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400616 one argument.
617 """
618 context = Context(TLSv1_METHOD)
619 self.assertRaises(TypeError, context.set_app_data)
620 self.assertRaises(TypeError, context.set_app_data, None, None)
621
622
623 def test_get_app_data_wrong_args(self):
624 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900625 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400626 arguments.
627 """
628 context = Context(TLSv1_METHOD)
629 self.assertRaises(TypeError, context.get_app_data, None)
630
631
632 def test_app_data(self):
633 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900634 :py:obj:`Context.set_app_data` stores an object for later retrieval using
635 :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400636 """
637 app_data = object()
638 context = Context(TLSv1_METHOD)
639 context.set_app_data(app_data)
640 self.assertIdentical(context.get_app_data(), app_data)
641
642
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400643 def test_set_options_wrong_args(self):
644 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900645 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with the wrong
646 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400647 """
648 context = Context(TLSv1_METHOD)
649 self.assertRaises(TypeError, context.set_options)
650 self.assertRaises(TypeError, context.set_options, None)
651 self.assertRaises(TypeError, context.set_options, 1, None)
652
653
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500654 def test_set_options(self):
655 """
656 :py:obj:`Context.set_options` returns the new options value.
657 """
658 context = Context(TLSv1_METHOD)
659 options = context.set_options(OP_NO_SSLv2)
660 self.assertTrue(OP_NO_SSLv2 & options)
661
662
663 if not PY3:
664 def test_set_options_long(self):
665 """
666 On Python 2 :py:obj:`Context.set_options` accepts values of type
667 :py:obj:`long` as well as :py:obj:`int`.
668 """
669 context = Context(TLSv1_METHOD)
670 options = context.set_options(long(OP_NO_SSLv2))
671 self.assertTrue(OP_NO_SSLv2 & options)
672
673
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300674 def test_set_mode_wrong_args(self):
675 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400676 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with the wrong
677 number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300678 """
679 context = Context(TLSv1_METHOD)
680 self.assertRaises(TypeError, context.set_mode)
681 self.assertRaises(TypeError, context.set_mode, None)
682 self.assertRaises(TypeError, context.set_mode, 1, None)
683
684
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400685 if MODE_RELEASE_BUFFERS is not None:
686 def test_set_mode(self):
687 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400688 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the newly
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400689 set mode.
690 """
691 context = Context(TLSv1_METHOD)
692 self.assertTrue(
693 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500694
695 if not PY3:
696 def test_set_mode_long(self):
697 """
698 On Python 2 :py:obj:`Context.set_mode` accepts values of type
699 :py:obj:`long` as well as :py:obj:`int`.
700 """
701 context = Context(TLSv1_METHOD)
702 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
703 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400704 else:
705 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
706
707
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400708 def test_set_timeout_wrong_args(self):
709 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900710 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with the wrong
711 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400712 """
713 context = Context(TLSv1_METHOD)
714 self.assertRaises(TypeError, context.set_timeout)
715 self.assertRaises(TypeError, context.set_timeout, None)
716 self.assertRaises(TypeError, context.set_timeout, 1, None)
717
718
719 def test_get_timeout_wrong_args(self):
720 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900721 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400722 """
723 context = Context(TLSv1_METHOD)
724 self.assertRaises(TypeError, context.get_timeout, None)
725
726
727 def test_timeout(self):
728 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900729 :py:obj:`Context.set_timeout` sets the session timeout for all connections
730 created using the context object. :py:obj:`Context.get_timeout` retrieves this
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400731 value.
732 """
733 context = Context(TLSv1_METHOD)
734 context.set_timeout(1234)
735 self.assertEquals(context.get_timeout(), 1234)
736
737
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500738 if not PY3:
739 def test_timeout_long(self):
740 """
741 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
742 `long` as well as int.
743 """
744 context = Context(TLSv1_METHOD)
745 context.set_timeout(long(1234))
746 self.assertEquals(context.get_timeout(), 1234)
747
748
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400749 def test_set_verify_depth_wrong_args(self):
750 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900751 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called with the wrong
752 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400753 """
754 context = Context(TLSv1_METHOD)
755 self.assertRaises(TypeError, context.set_verify_depth)
756 self.assertRaises(TypeError, context.set_verify_depth, None)
757 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
758
759
760 def test_get_verify_depth_wrong_args(self):
761 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900762 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400763 """
764 context = Context(TLSv1_METHOD)
765 self.assertRaises(TypeError, context.get_verify_depth, None)
766
767
768 def test_verify_depth(self):
769 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900770 :py:obj:`Context.set_verify_depth` sets the number of certificates in a chain
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400771 to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900772 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400773 """
774 context = Context(TLSv1_METHOD)
775 context.set_verify_depth(11)
776 self.assertEquals(context.get_verify_depth(), 11)
777
778
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500779 if not PY3:
780 def test_verify_depth_long(self):
781 """
782 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
783 type `long` as well as int.
784 """
785 context = Context(TLSv1_METHOD)
786 context.set_verify_depth(long(11))
787 self.assertEquals(context.get_verify_depth(), 11)
788
789
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400790 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400791 """
792 Write a new private key out to a new file, encrypted using the given
793 passphrase. Return the path to the new file.
794 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400795 key = PKey()
796 key.generate_key(TYPE_RSA, 128)
797 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400798 fObj = open(pemFile, 'w')
799 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
800 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400801 fObj.close()
802 return pemFile
803
804
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400805 def test_set_passwd_cb_wrong_args(self):
806 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900807 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called with the
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400808 wrong arguments or with a non-callable first argument.
809 """
810 context = Context(TLSv1_METHOD)
811 self.assertRaises(TypeError, context.set_passwd_cb)
812 self.assertRaises(TypeError, context.set_passwd_cb, None)
813 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
814
815
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400816 def test_set_passwd_cb(self):
817 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900818 :py:obj:`Context.set_passwd_cb` accepts a callable which will be invoked when
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400819 a private key is loaded from an encrypted PEM.
820 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400821 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400822 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400823 calledWith = []
824 def passphraseCallback(maxlen, verify, extra):
825 calledWith.append((maxlen, verify, extra))
826 return passphrase
827 context = Context(TLSv1_METHOD)
828 context.set_passwd_cb(passphraseCallback)
829 context.use_privatekey_file(pemFile)
830 self.assertTrue(len(calledWith), 1)
831 self.assertTrue(isinstance(calledWith[0][0], int))
832 self.assertTrue(isinstance(calledWith[0][1], int))
833 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400834
835
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400836 def test_passwd_callback_exception(self):
837 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900838 :py:obj:`Context.use_privatekey_file` propagates any exception raised by the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400839 passphrase callback.
840 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400841 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400842 def passphraseCallback(maxlen, verify, extra):
843 raise RuntimeError("Sorry, I am a fail.")
844
845 context = Context(TLSv1_METHOD)
846 context.set_passwd_cb(passphraseCallback)
847 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
848
849
850 def test_passwd_callback_false(self):
851 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900852 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400853 passphrase callback returns a false value.
854 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400855 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400856 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500857 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400858
859 context = Context(TLSv1_METHOD)
860 context.set_passwd_cb(passphraseCallback)
861 self.assertRaises(Error, context.use_privatekey_file, pemFile)
862
863
864 def test_passwd_callback_non_string(self):
865 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900866 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400867 passphrase callback returns a true non-string value.
868 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400869 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400870 def passphraseCallback(maxlen, verify, extra):
871 return 10
872
873 context = Context(TLSv1_METHOD)
874 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800875 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400876
877
878 def test_passwd_callback_too_long(self):
879 """
880 If the passphrase returned by the passphrase callback returns a string
881 longer than the indicated maximum length, it is truncated.
882 """
883 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400884 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400885 pemFile = self._write_encrypted_pem(passphrase)
886 def passphraseCallback(maxlen, verify, extra):
887 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400888 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400889
890 context = Context(TLSv1_METHOD)
891 context.set_passwd_cb(passphraseCallback)
892 # This shall succeed because the truncated result is the correct
893 # passphrase.
894 context.use_privatekey_file(pemFile)
895
896
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400897 def test_set_info_callback(self):
898 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900899 :py:obj:`Context.set_info_callback` accepts a callable which will be invoked
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400900 when certain information about an SSL connection is available.
901 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500902 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400903
904 clientSSL = Connection(Context(TLSv1_METHOD), client)
905 clientSSL.set_connect_state()
906
907 called = []
908 def info(conn, where, ret):
909 called.append((conn, where, ret))
910 context = Context(TLSv1_METHOD)
911 context.set_info_callback(info)
912 context.use_certificate(
913 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
914 context.use_privatekey(
915 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
916
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400917 serverSSL = Connection(context, server)
918 serverSSL.set_accept_state()
919
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500920 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400921
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500922 # The callback must always be called with a Connection instance as the
923 # first argument. It would probably be better to split this into
924 # separate tests for client and server side info callbacks so we could
925 # assert it is called with the right Connection instance. It would
926 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500927 notConnections = [
928 conn for (conn, where, ret) in called
929 if not isinstance(conn, Connection)]
930 self.assertEqual(
931 [], notConnections,
932 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400933
934
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400935 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400936 """
937 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400938 its :py:obj:`load_verify_locations` method with the given arguments.
939 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400940 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500941 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400942
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400943 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400944 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400945 # Require that the server certificate verify properly or the
946 # connection will fail.
947 clientContext.set_verify(
948 VERIFY_PEER,
949 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
950
951 clientSSL = Connection(clientContext, client)
952 clientSSL.set_connect_state()
953
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400954 serverContext = Context(TLSv1_METHOD)
955 serverContext.use_certificate(
956 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
957 serverContext.use_privatekey(
958 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
959
960 serverSSL = Connection(serverContext, server)
961 serverSSL.set_accept_state()
962
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400963 # Without load_verify_locations above, the handshake
964 # will fail:
965 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
966 # 'certificate verify failed')]
967 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400968
969 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400970 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400971
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500972
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400973 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400974 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400975 Verify that if path to a file containing a certificate is passed to
976 ``Context.load_verify_locations`` for the ``cafile`` parameter, that
977 certificate is used as a trust root for the purposes of verifying
978 connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400979 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400980 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400981 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400982 fObj.close()
983
984 self._load_verify_locations_test(cafile)
985
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400986
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400987 def test_load_verify_bytes_cafile(self):
988 """
989 :py:obj:`Context.load_verify_locations` accepts a file name as a
990 ``bytes`` instance and uses the certificates within for verification
991 purposes.
992 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400993 cafile = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400994 self._load_verify_cafile(cafile)
995
996
997 def test_load_verify_unicode_cafile(self):
998 """
999 :py:obj:`Context.load_verify_locations` accepts a file name as a
1000 ``unicode`` instance and uses the certificates within for verification
1001 purposes.
1002 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001003 self._load_verify_cafile(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001004 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001005 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001006
1007
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001008 def test_load_verify_invalid_file(self):
1009 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001010 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when passed a
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001011 non-existent cafile.
1012 """
1013 clientContext = Context(TLSv1_METHOD)
1014 self.assertRaises(
1015 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001016
1017
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001018 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001019 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001020 Verify that if path to a directory containing certificate files is
1021 passed to ``Context.load_verify_locations`` for the ``capath``
1022 parameter, those certificates are used as trust roots for the purposes
1023 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001024 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001025 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001026 # Hash values computed manually with c_rehash to avoid depending on
1027 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1028 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001029 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001030 cafile = join_bytes_or_unicode(capath, name)
1031 with open(cafile, 'w') as fObj:
1032 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001033
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001034 self._load_verify_locations_test(None, capath)
1035
1036
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001037 def test_load_verify_directory_bytes_capath(self):
1038 """
1039 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1040 ``bytes`` instance and uses the certificates within for verification
1041 purposes.
1042 """
1043 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001044 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001045 )
1046
1047
1048 def test_load_verify_directory_unicode_capath(self):
1049 """
1050 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1051 ``unicode`` instance and uses the certificates within for verification
1052 purposes.
1053 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001054 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001055 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001056 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001057
1058
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001059 def test_load_verify_locations_wrong_args(self):
1060 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001061 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if called with
1062 the wrong number of arguments or with non-:py:obj:`str` arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001063 """
1064 context = Context(TLSv1_METHOD)
1065 self.assertRaises(TypeError, context.load_verify_locations)
1066 self.assertRaises(TypeError, context.load_verify_locations, object())
1067 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
1068 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
1069
1070
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001071 if platform == "win32":
1072 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001073 "See LP#404343 and LP#404344."
1074 else:
1075 def test_set_default_verify_paths(self):
1076 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001077 :py:obj:`Context.set_default_verify_paths` causes the platform-specific CA
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001078 certificate locations to be used for verification purposes.
1079 """
1080 # Testing this requires a server with a certificate signed by one of
1081 # the CAs in the platform CA location. Getting one of those costs
1082 # money. Fortunately (or unfortunately, depending on your
1083 # perspective), it's easy to think of a public server on the
1084 # internet which has such a certificate. Connecting to the network
1085 # in a unit test is bad, but it's the only way I can think of to
1086 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001087
Alex Gaynorb586da32014-11-15 09:22:21 -08001088 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
1089 context = Context(TLSv1_METHOD)
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001090 context.set_default_verify_paths()
1091 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02001092 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001093 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001094
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001095 client = socket()
1096 client.connect(('verisign.com', 443))
1097 clientSSL = Connection(context, client)
1098 clientSSL.set_connect_state()
1099 clientSSL.do_handshake()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001100 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001101 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001102
1103
1104 def test_set_default_verify_paths_signature(self):
1105 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001106 :py:obj:`Context.set_default_verify_paths` takes no arguments and raises
1107 :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001108 """
1109 context = Context(TLSv1_METHOD)
1110 self.assertRaises(TypeError, context.set_default_verify_paths, None)
1111 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
1112 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001113
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001114
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001115 def test_add_extra_chain_cert_invalid_cert(self):
1116 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001117 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if called with
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001118 other than one argument or if called with an object which is not an
Jonathan Ballet648875f2011-07-16 14:14:58 +09001119 instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001120 """
1121 context = Context(TLSv1_METHOD)
1122 self.assertRaises(TypeError, context.add_extra_chain_cert)
1123 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
1124 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
1125
1126
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001127 def _handshake_test(self, serverContext, clientContext):
1128 """
1129 Verify that a client and server created with the given contexts can
1130 successfully handshake and communicate.
1131 """
1132 serverSocket, clientSocket = socket_pair()
1133
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001134 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001135 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001136
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001137 client = Connection(clientContext, clientSocket)
1138 client.set_connect_state()
1139
1140 # Make them talk to each other.
1141 # self._interactInMemory(client, server)
1142 for i in range(3):
1143 for s in [client, server]:
1144 try:
1145 s.do_handshake()
1146 except WantReadError:
1147 pass
1148
1149
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001150 def test_set_verify_callback_connection_argument(self):
1151 """
1152 The first argument passed to the verify callback is the
1153 :py:class:`Connection` instance for which verification is taking place.
1154 """
1155 serverContext = Context(TLSv1_METHOD)
1156 serverContext.use_privatekey(
1157 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1158 serverContext.use_certificate(
1159 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1160 serverConnection = Connection(serverContext, None)
1161
1162 class VerifyCallback(object):
1163 def callback(self, connection, *args):
1164 self.connection = connection
1165 return 1
1166
1167 verify = VerifyCallback()
1168 clientContext = Context(TLSv1_METHOD)
1169 clientContext.set_verify(VERIFY_PEER, verify.callback)
1170 clientConnection = Connection(clientContext, None)
1171 clientConnection.set_connect_state()
1172
1173 self._handshakeInMemory(clientConnection, serverConnection)
1174
1175 self.assertIdentical(verify.connection, clientConnection)
1176
1177
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001178 def test_set_verify_callback_exception(self):
1179 """
1180 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1181 exception, verification fails and the exception is propagated to the
1182 caller of :py:obj:`Connection.do_handshake`.
1183 """
1184 serverContext = Context(TLSv1_METHOD)
1185 serverContext.use_privatekey(
1186 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1187 serverContext.use_certificate(
1188 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1189
1190 clientContext = Context(TLSv1_METHOD)
1191 def verify_callback(*args):
1192 raise Exception("silly verify failure")
1193 clientContext.set_verify(VERIFY_PEER, verify_callback)
1194
1195 exc = self.assertRaises(
1196 Exception, self._handshake_test, serverContext, clientContext)
1197 self.assertEqual("silly verify failure", str(exc))
1198
1199
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001200 def test_add_extra_chain_cert(self):
1201 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001202 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509`
1203 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001204
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001205 See :py:obj:`_create_certificate_chain` for the details of the
1206 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001207
1208 The chain is tested by starting a server with scert and connecting
1209 to it with a client which trusts cacert and requires verification to
1210 succeed.
1211 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001212 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001213 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1214
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001215 # Dump the CA certificate to a file because that's the only way to load
1216 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001217 for cert, name in [(cacert, 'ca.pem'),
1218 (icert, 'i.pem'),
1219 (scert, 's.pem')]:
1220 fObj = open(join(self.tmpdir, name), 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001221 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001222 fObj.close()
1223
Hynek Schlawack1902c012015-04-16 15:06:41 -04001224 for key, name in [(cakey, 'ca.key'),
1225 (ikey, 'i.key'),
1226 (skey, 's.key')]:
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001227 fObj = open(join(self.tmpdir, name), 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001228 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001229 fObj.close()
1230
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001231 # Create the server context
1232 serverContext = Context(TLSv1_METHOD)
1233 serverContext.use_privatekey(skey)
1234 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001235 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001236 serverContext.add_extra_chain_cert(icert)
1237
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001238 # Create the client
1239 clientContext = Context(TLSv1_METHOD)
1240 clientContext.set_verify(
1241 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001242 clientContext.load_verify_locations(join(self.tmpdir, "ca.pem"))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001243
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001244 # Try it out.
1245 self._handshake_test(serverContext, clientContext)
1246
1247
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001248 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001249 """
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001250 Verify that :py:obj:`Context.use_certificate_chain_file` reads a
1251 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001252
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001253 The chain is tested by starting a server with scert and connecting to
1254 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001255 succeed.
1256 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001257 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001258 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1259
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001260 makedirs(certdir)
1261
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001262 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1263 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001264
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001265 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001266 with open(chainFile, 'wb') as fObj:
1267 # Most specific to least general.
1268 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1269 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1270 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1271
1272 with open(caFile, 'w') as fObj:
1273 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001274
1275 serverContext = Context(TLSv1_METHOD)
1276 serverContext.use_certificate_chain_file(chainFile)
1277 serverContext.use_privatekey(skey)
1278
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001279 clientContext = Context(TLSv1_METHOD)
1280 clientContext.set_verify(
1281 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001282 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001283
1284 self._handshake_test(serverContext, clientContext)
1285
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001286
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001287 def test_use_certificate_chain_file_bytes(self):
1288 """
1289 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1290 an instance of ``bytes``) to specify additional certificates to use to
1291 construct and verify a trust chain.
1292 """
1293 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001294 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001295 )
1296
1297
1298 def test_use_certificate_chain_file_unicode(self):
1299 """
1300 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1301 an instance of ``unicode``) to specify additional certificates to use
1302 to construct and verify a trust chain.
1303 """
1304 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001305 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001306 )
1307
1308
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001309 def test_use_certificate_chain_file_wrong_args(self):
1310 """
1311 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1312 if passed zero or more than one argument or when passed a non-byte
1313 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error` when
1314 passed a bad chain file name (for example, the name of a file which does
1315 not exist).
1316 """
1317 context = Context(TLSv1_METHOD)
1318 self.assertRaises(TypeError, context.use_certificate_chain_file)
1319 self.assertRaises(TypeError, context.use_certificate_chain_file, object())
1320 self.assertRaises(TypeError, context.use_certificate_chain_file, b"foo", object())
1321
1322 self.assertRaises(Error, context.use_certificate_chain_file, self.mktemp())
1323
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001324 # XXX load_client_ca
1325 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001326
1327 def test_get_verify_mode_wrong_args(self):
1328 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001329 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001330 arguments.
1331 """
1332 context = Context(TLSv1_METHOD)
1333 self.assertRaises(TypeError, context.get_verify_mode, None)
1334
1335
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001336 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001337 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001338 :py:obj:`Context.get_verify_mode` returns the verify mode flags previously
1339 passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001340 """
1341 context = Context(TLSv1_METHOD)
1342 self.assertEquals(context.get_verify_mode(), 0)
1343 context.set_verify(
1344 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1345 self.assertEquals(
1346 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1347
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001348
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001349 if not PY3:
1350 def test_set_verify_mode_long(self):
1351 """
1352 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1353 type :py:obj:`long` as well as :py:obj:`int`.
1354 """
1355 context = Context(TLSv1_METHOD)
1356 self.assertEquals(context.get_verify_mode(), 0)
1357 context.set_verify(
1358 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None)
1359 self.assertEquals(
1360 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1361
1362
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001363 def test_load_tmp_dh_wrong_args(self):
1364 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001365 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
1366 number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001367 """
1368 context = Context(TLSv1_METHOD)
1369 self.assertRaises(TypeError, context.load_tmp_dh)
1370 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1371 self.assertRaises(TypeError, context.load_tmp_dh, object())
1372
1373
1374 def test_load_tmp_dh_missing_file(self):
1375 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001376 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the specified file
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001377 does not exist.
1378 """
1379 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001380 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001381
1382
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001383 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001384 """
1385 Verify that calling ``Context.load_tmp_dh`` with the given filename
1386 does not raise an exception.
1387 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001388 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001389 with open(dhfilename, "w") as dhfile:
1390 dhfile.write(dhparam)
1391
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001392 context.load_tmp_dh(dhfilename)
1393 # XXX What should I assert here? -exarkun
1394
1395
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001396 def test_load_tmp_dh_bytes(self):
1397 """
1398 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1399 specified file (given as ``bytes``).
1400 """
1401 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001402 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001403 )
1404
1405
1406 def test_load_tmp_dh_unicode(self):
1407 """
1408 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1409 specified file (given as ``unicode``).
1410 """
1411 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001412 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001413 )
1414
1415
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001416 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001417 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001418 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001419 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001420 """
1421 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001422 for curve in get_elliptic_curves():
1423 # The only easily "assertable" thing is that it does not raise an
1424 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001425 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001426
1427
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001428 def test_set_cipher_list_bytes(self):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001429 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001430 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
1431 ciphers which connections created with the context object will be able
1432 to choose from.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001433 """
1434 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001435 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001436 conn = Connection(context, None)
1437 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001438
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001439
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001440 def test_set_cipher_list_text(self):
1441 """
1442 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
1443 the ciphers which connections created with the context object will be
1444 able to choose from.
1445 """
1446 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -05001447 context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001448 conn = Connection(context, None)
1449 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
1450
1451
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001452 def test_set_cipher_list_wrong_args(self):
1453 """
Jean-Paul Calderone17044832014-01-18 10:20:11 -05001454 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
1455 passed zero arguments or more than one argument or when passed a
1456 non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001457 passed an incorrect cipher list string.
1458 """
1459 context = Context(TLSv1_METHOD)
1460 self.assertRaises(TypeError, context.set_cipher_list)
1461 self.assertRaises(TypeError, context.set_cipher_list, object())
1462 self.assertRaises(TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object())
1463
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001464 self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001465
1466
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001467 def test_set_session_cache_mode_wrong_args(self):
1468 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001469 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1470 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001471 """
1472 context = Context(TLSv1_METHOD)
1473 self.assertRaises(TypeError, context.set_session_cache_mode)
1474 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1475
1476
1477 def test_get_session_cache_mode_wrong_args(self):
1478 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001479 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1480 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001481 """
1482 context = Context(TLSv1_METHOD)
1483 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1484
1485
1486 def test_session_cache_mode(self):
1487 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001488 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1489 cached. The setting can be retrieved via
1490 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001491 """
1492 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001493 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001494 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1495 self.assertEqual(SESS_CACHE_OFF, off)
1496 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1497
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001498 if not PY3:
1499 def test_session_cache_mode_long(self):
1500 """
1501 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1502 of type :py:obj:`long` as well as :py:obj:`int`.
1503 """
1504 context = Context(TLSv1_METHOD)
1505 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1506 self.assertEqual(
1507 SESS_CACHE_BOTH, context.get_session_cache_mode())
1508
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001509
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001510 def test_get_cert_store(self):
1511 """
1512 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store` instance.
1513 """
1514 context = Context(TLSv1_METHOD)
1515 store = context.get_cert_store()
1516 self.assertIsInstance(store, X509Store)
1517
1518
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001519
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001520class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1521 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001522 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
1523 :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001524 """
1525 def test_wrong_args(self):
1526 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001527 :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001528 with other than one argument.
1529 """
1530 context = Context(TLSv1_METHOD)
1531 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1532 self.assertRaises(
1533 TypeError, context.set_tlsext_servername_callback, 1, 2)
1534
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001535
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001536 def test_old_callback_forgotten(self):
1537 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001538 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001539 callback, the one it replaces is dereferenced.
1540 """
1541 def callback(connection):
1542 pass
1543
1544 def replacement(connection):
1545 pass
1546
1547 context = Context(TLSv1_METHOD)
1548 context.set_tlsext_servername_callback(callback)
1549
1550 tracker = ref(callback)
1551 del callback
1552
1553 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001554
1555 # One run of the garbage collector happens to work on CPython. PyPy
1556 # doesn't collect the underlying object until a second run for whatever
1557 # reason. That's fine, it still demonstrates our code has properly
1558 # dropped the reference.
1559 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001560 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001561
1562 callback = tracker()
1563 if callback is not None:
1564 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001565 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001566 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001567
1568
1569 def test_no_servername(self):
1570 """
1571 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001572 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
1573 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001574 """
1575 args = []
1576 def servername(conn):
1577 args.append((conn, conn.get_servername()))
1578 context = Context(TLSv1_METHOD)
1579 context.set_tlsext_servername_callback(servername)
1580
1581 # Lose our reference to it. The Context is responsible for keeping it
1582 # alive now.
1583 del servername
1584 collect()
1585
1586 # Necessary to actually accept the connection
1587 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1588 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1589
1590 # Do a little connection to trigger the logic
1591 server = Connection(context, None)
1592 server.set_accept_state()
1593
1594 client = Connection(Context(TLSv1_METHOD), None)
1595 client.set_connect_state()
1596
1597 self._interactInMemory(server, client)
1598
1599 self.assertEqual([(server, None)], args)
1600
1601
1602 def test_servername(self):
1603 """
1604 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +09001605 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
1606 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001607 """
1608 args = []
1609 def servername(conn):
1610 args.append((conn, conn.get_servername()))
1611 context = Context(TLSv1_METHOD)
1612 context.set_tlsext_servername_callback(servername)
1613
1614 # Necessary to actually accept the connection
1615 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1616 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1617
1618 # Do a little connection to trigger the logic
1619 server = Connection(context, None)
1620 server.set_accept_state()
1621
1622 client = Connection(Context(TLSv1_METHOD), None)
1623 client.set_connect_state()
1624 client.set_tlsext_host_name(b("foo1.example.com"))
1625
1626 self._interactInMemory(server, client)
1627
1628 self.assertEqual([(server, b("foo1.example.com"))], args)
1629
1630
Cory Benfield84a121e2014-03-31 20:30:25 +01001631class NextProtoNegotiationTests(TestCase, _LoopbackMixin):
1632 """
1633 Test for Next Protocol Negotiation in PyOpenSSL.
1634 """
Cory Benfieldba1820d2015-04-13 17:39:12 -04001635 if _lib.Cryptography_HAS_NEXTPROTONEG:
1636 def test_npn_success(self):
1637 """
1638 Tests that clients and servers that agree on the negotiated next
1639 protocol can correct establish a connection, and that the agreed
1640 protocol is reported by the connections.
1641 """
1642 advertise_args = []
1643 select_args = []
1644 def advertise(conn):
1645 advertise_args.append((conn,))
1646 return [b'http/1.1', b'spdy/2']
1647 def select(conn, options):
1648 select_args.append((conn, options))
1649 return b'spdy/2'
Cory Benfield84a121e2014-03-31 20:30:25 +01001650
Cory Benfieldba1820d2015-04-13 17:39:12 -04001651 server_context = Context(TLSv1_METHOD)
1652 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001653
Cory Benfieldba1820d2015-04-13 17:39:12 -04001654 client_context = Context(TLSv1_METHOD)
1655 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001656
Cory Benfieldba1820d2015-04-13 17:39:12 -04001657 # Necessary to actually accept the connection
1658 server_context.use_privatekey(
1659 load_privatekey(FILETYPE_PEM, server_key_pem))
1660 server_context.use_certificate(
1661 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001662
Cory Benfieldba1820d2015-04-13 17:39:12 -04001663 # Do a little connection to trigger the logic
1664 server = Connection(server_context, None)
1665 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001666
Cory Benfieldba1820d2015-04-13 17:39:12 -04001667 client = Connection(client_context, None)
1668 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001669
Cory Benfieldba1820d2015-04-13 17:39:12 -04001670 self._interactInMemory(server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001671
Cory Benfieldba1820d2015-04-13 17:39:12 -04001672 self.assertEqual([(server,)], advertise_args)
1673 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001674
Cory Benfieldba1820d2015-04-13 17:39:12 -04001675 self.assertEqual(server.get_next_proto_negotiated(), b'spdy/2')
1676 self.assertEqual(client.get_next_proto_negotiated(), b'spdy/2')
Cory Benfield84a121e2014-03-31 20:30:25 +01001677
1678
Cory Benfieldba1820d2015-04-13 17:39:12 -04001679 def test_npn_client_fail(self):
1680 """
1681 Tests that when clients and servers cannot agree on what protocol
1682 to use next that the TLS connection does not get established.
1683 """
1684 advertise_args = []
1685 select_args = []
1686 def advertise(conn):
1687 advertise_args.append((conn,))
1688 return [b'http/1.1', b'spdy/2']
1689 def select(conn, options):
1690 select_args.append((conn, options))
1691 return b''
Cory Benfield84a121e2014-03-31 20:30:25 +01001692
Cory Benfieldba1820d2015-04-13 17:39:12 -04001693 server_context = Context(TLSv1_METHOD)
1694 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001695
Cory Benfieldba1820d2015-04-13 17:39:12 -04001696 client_context = Context(TLSv1_METHOD)
1697 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001698
Cory Benfieldba1820d2015-04-13 17:39:12 -04001699 # Necessary to actually accept the connection
1700 server_context.use_privatekey(
1701 load_privatekey(FILETYPE_PEM, server_key_pem))
1702 server_context.use_certificate(
1703 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001704
Cory Benfieldba1820d2015-04-13 17:39:12 -04001705 # Do a little connection to trigger the logic
1706 server = Connection(server_context, None)
1707 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001708
Cory Benfieldba1820d2015-04-13 17:39:12 -04001709 client = Connection(client_context, None)
1710 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001711
Cory Benfieldba1820d2015-04-13 17:39:12 -04001712 # If the client doesn't return anything, the connection will fail.
1713 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001714
Cory Benfieldba1820d2015-04-13 17:39:12 -04001715 self.assertEqual([(server,)], advertise_args)
1716 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001717
1718
Cory Benfieldba1820d2015-04-13 17:39:12 -04001719 def test_npn_select_error(self):
1720 """
1721 Test that we can handle exceptions in the select callback. If
1722 select fails it should be fatal to the connection.
1723 """
1724 advertise_args = []
1725 def advertise(conn):
1726 advertise_args.append((conn,))
1727 return [b'http/1.1', b'spdy/2']
1728 def select(conn, options):
1729 raise TypeError
Cory Benfield0ea76e72015-03-22 09:05:28 +00001730
Cory Benfieldba1820d2015-04-13 17:39:12 -04001731 server_context = Context(TLSv1_METHOD)
1732 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001733
Cory Benfieldba1820d2015-04-13 17:39:12 -04001734 client_context = Context(TLSv1_METHOD)
1735 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001736
Cory Benfieldba1820d2015-04-13 17:39:12 -04001737 # Necessary to actually accept the connection
1738 server_context.use_privatekey(
1739 load_privatekey(FILETYPE_PEM, server_key_pem))
1740 server_context.use_certificate(
1741 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001742
Cory Benfieldba1820d2015-04-13 17:39:12 -04001743 # Do a little connection to trigger the logic
1744 server = Connection(server_context, None)
1745 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001746
Cory Benfieldba1820d2015-04-13 17:39:12 -04001747 client = Connection(client_context, None)
1748 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001749
Cory Benfieldba1820d2015-04-13 17:39:12 -04001750 # If the callback throws an exception it should be raised here.
1751 self.assertRaises(
1752 TypeError, self._interactInMemory, server, client
1753 )
1754 self.assertEqual([(server,)], advertise_args)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001755
1756
Cory Benfieldba1820d2015-04-13 17:39:12 -04001757 def test_npn_advertise_error(self):
1758 """
1759 Test that we can handle exceptions in the advertise callback. If
1760 advertise fails no NPN is advertised to the client.
1761 """
1762 select_args = []
1763 def advertise(conn):
1764 raise TypeError
1765 def select(conn, options):
1766 select_args.append((conn, options))
1767 return b''
Cory Benfield0ea76e72015-03-22 09:05:28 +00001768
Cory Benfieldba1820d2015-04-13 17:39:12 -04001769 server_context = Context(TLSv1_METHOD)
1770 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001771
Cory Benfieldba1820d2015-04-13 17:39:12 -04001772 client_context = Context(TLSv1_METHOD)
1773 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001774
Cory Benfieldba1820d2015-04-13 17:39:12 -04001775 # Necessary to actually accept the connection
1776 server_context.use_privatekey(
1777 load_privatekey(FILETYPE_PEM, server_key_pem))
1778 server_context.use_certificate(
1779 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001780
Cory Benfieldba1820d2015-04-13 17:39:12 -04001781 # Do a little connection to trigger the logic
1782 server = Connection(server_context, None)
1783 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001784
Cory Benfieldba1820d2015-04-13 17:39:12 -04001785 client = Connection(client_context, None)
1786 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001787
Cory Benfieldba1820d2015-04-13 17:39:12 -04001788 # If the client doesn't return anything, the connection will fail.
1789 self.assertRaises(
1790 TypeError, self._interactInMemory, server, client
1791 )
1792 self.assertEqual([], select_args)
1793
1794 else:
1795 # No NPN.
1796 def test_npn_not_implemented(self):
1797 # Test the context methods first.
1798 context = Context(TLSv1_METHOD)
1799 fail_methods = [
1800 context.set_npn_advertise_callback,
1801 context.set_npn_select_callback,
1802 ]
1803 for method in fail_methods:
1804 self.assertRaises(
1805 NotImplementedError, method, None
1806 )
1807
1808 # Now test a connection.
1809 conn = Connection(context)
1810 fail_methods = [
1811 conn.get_next_proto_negotiated,
1812 ]
1813 for method in fail_methods:
1814 self.assertRaises(NotImplementedError, method)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001815
1816
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001817
Cory Benfield12eae892014-06-07 15:42:56 +01001818class ApplicationLayerProtoNegotiationTests(TestCase, _LoopbackMixin):
1819 """
1820 Tests for ALPN in PyOpenSSL.
1821 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001822 # Skip tests on versions that don't support ALPN.
1823 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001824
Cory Benfielde46fa842015-04-13 16:50:49 -04001825 def test_alpn_success(self):
1826 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001827 Clients and servers that agree on the negotiated ALPN protocol can
1828 correct establish a connection, and the agreed protocol is reported
1829 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001830 """
1831 select_args = []
1832 def select(conn, options):
1833 select_args.append((conn, options))
1834 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001835
Cory Benfielde46fa842015-04-13 16:50:49 -04001836 client_context = Context(TLSv1_METHOD)
1837 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001838
Cory Benfielde46fa842015-04-13 16:50:49 -04001839 server_context = Context(TLSv1_METHOD)
1840 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001841
Cory Benfielde46fa842015-04-13 16:50:49 -04001842 # Necessary to actually accept the connection
1843 server_context.use_privatekey(
1844 load_privatekey(FILETYPE_PEM, server_key_pem))
1845 server_context.use_certificate(
1846 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001847
Cory Benfielde46fa842015-04-13 16:50:49 -04001848 # Do a little connection to trigger the logic
1849 server = Connection(server_context, None)
1850 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001851
Cory Benfielde46fa842015-04-13 16:50:49 -04001852 client = Connection(client_context, None)
1853 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001854
Cory Benfielde46fa842015-04-13 16:50:49 -04001855 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001856
Cory Benfielde46fa842015-04-13 16:50:49 -04001857 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
1858
1859 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1860 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001861
1862
Cory Benfielde46fa842015-04-13 16:50:49 -04001863 def test_alpn_set_on_connection(self):
1864 """
1865 The same as test_alpn_success, but setting the ALPN protocols on
1866 the connection rather than the context.
1867 """
1868 select_args = []
1869 def select(conn, options):
1870 select_args.append((conn, options))
1871 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001872
Cory Benfielde46fa842015-04-13 16:50:49 -04001873 # Setup the client context but don't set any ALPN protocols.
1874 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001875
Cory Benfielde46fa842015-04-13 16:50:49 -04001876 server_context = Context(TLSv1_METHOD)
1877 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001878
Cory Benfielde46fa842015-04-13 16:50:49 -04001879 # Necessary to actually accept the connection
1880 server_context.use_privatekey(
1881 load_privatekey(FILETYPE_PEM, server_key_pem))
1882 server_context.use_certificate(
1883 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001884
Cory Benfielde46fa842015-04-13 16:50:49 -04001885 # Do a little connection to trigger the logic
1886 server = Connection(server_context, None)
1887 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001888
Cory Benfielde46fa842015-04-13 16:50:49 -04001889 # Set the ALPN protocols on the client connection.
1890 client = Connection(client_context, None)
1891 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1892 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001893
Cory Benfielde46fa842015-04-13 16:50:49 -04001894 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001895
Cory Benfielde46fa842015-04-13 16:50:49 -04001896 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001897
Cory Benfielde46fa842015-04-13 16:50:49 -04001898 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1899 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001900
1901
Cory Benfielde46fa842015-04-13 16:50:49 -04001902 def test_alpn_server_fail(self):
1903 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001904 When clients and servers cannot agree on what protocol to use next
1905 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001906 """
1907 select_args = []
1908 def select(conn, options):
1909 select_args.append((conn, options))
1910 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001911
Cory Benfielde46fa842015-04-13 16:50:49 -04001912 client_context = Context(TLSv1_METHOD)
1913 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001914
Cory Benfielde46fa842015-04-13 16:50:49 -04001915 server_context = Context(TLSv1_METHOD)
1916 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001917
Cory Benfielde46fa842015-04-13 16:50:49 -04001918 # Necessary to actually accept the connection
1919 server_context.use_privatekey(
1920 load_privatekey(FILETYPE_PEM, server_key_pem))
1921 server_context.use_certificate(
1922 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001923
Cory Benfielde46fa842015-04-13 16:50:49 -04001924 # Do a little connection to trigger the logic
1925 server = Connection(server_context, None)
1926 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001927
Cory Benfielde46fa842015-04-13 16:50:49 -04001928 client = Connection(client_context, None)
1929 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001930
Cory Benfielde46fa842015-04-13 16:50:49 -04001931 # If the client doesn't return anything, the connection will fail.
1932 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001933
Cory Benfielde46fa842015-04-13 16:50:49 -04001934 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001935
1936
Cory Benfielde46fa842015-04-13 16:50:49 -04001937 def test_alpn_no_server(self):
1938 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001939 When clients and servers cannot agree on what protocol to use next
1940 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04001941 """
1942 client_context = Context(TLSv1_METHOD)
1943 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04001944
Cory Benfielde46fa842015-04-13 16:50:49 -04001945 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04001946
Cory Benfielde46fa842015-04-13 16:50:49 -04001947 # Necessary to actually accept the connection
1948 server_context.use_privatekey(
1949 load_privatekey(FILETYPE_PEM, server_key_pem))
1950 server_context.use_certificate(
1951 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04001952
Cory Benfielde46fa842015-04-13 16:50:49 -04001953 # Do a little connection to trigger the logic
1954 server = Connection(server_context, None)
1955 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001956
Cory Benfielde46fa842015-04-13 16:50:49 -04001957 client = Connection(client_context, None)
1958 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001959
Cory Benfielde46fa842015-04-13 16:50:49 -04001960 # Do the dance.
1961 self._interactInMemory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04001962
Cory Benfielde46fa842015-04-13 16:50:49 -04001963 self.assertEqual(client.get_alpn_proto_negotiated(), b'')
Cory Benfielde3d57152015-04-11 17:57:35 -04001964
1965
Cory Benfielde46fa842015-04-13 16:50:49 -04001966 def test_alpn_callback_exception(self):
1967 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001968 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04001969 """
1970 select_args = []
1971 def select(conn, options):
1972 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04001973 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001974
Cory Benfielde46fa842015-04-13 16:50:49 -04001975 client_context = Context(TLSv1_METHOD)
1976 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04001977
Cory Benfielde46fa842015-04-13 16:50:49 -04001978 server_context = Context(TLSv1_METHOD)
1979 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04001980
Cory Benfielde46fa842015-04-13 16:50:49 -04001981 # Necessary to actually accept the connection
1982 server_context.use_privatekey(
1983 load_privatekey(FILETYPE_PEM, server_key_pem))
1984 server_context.use_certificate(
1985 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04001986
Cory Benfielde46fa842015-04-13 16:50:49 -04001987 # Do a little connection to trigger the logic
1988 server = Connection(server_context, None)
1989 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001990
Cory Benfielde46fa842015-04-13 16:50:49 -04001991 client = Connection(client_context, None)
1992 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001993
Cory Benfielde46fa842015-04-13 16:50:49 -04001994 self.assertRaises(
1995 TypeError, self._interactInMemory, server, client
1996 )
1997 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfieldf1177e72015-04-12 09:11:49 -04001998
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001999 else:
2000 # No ALPN.
2001 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04002002 """
2003 If ALPN is not in OpenSSL, we should raise NotImplementedError.
2004 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002005 # Test the context methods first.
2006 context = Context(TLSv1_METHOD)
Cory Benfield307e9e62015-04-13 18:21:12 -04002007 self.assertRaises(
2008 NotImplementedError, context.set_alpn_protos, None
2009 )
2010 self.assertRaises(
2011 NotImplementedError, context.set_alpn_select_callback, None
2012 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002013
2014 # Now test a connection.
2015 conn = Connection(context)
Cory Benfield307e9e62015-04-13 18:21:12 -04002016 self.assertRaises(
2017 NotImplementedError, context.set_alpn_protos, None
2018 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002019
Cory Benfieldf1177e72015-04-12 09:11:49 -04002020
Cory Benfield12eae892014-06-07 15:42:56 +01002021
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002022class SessionTests(TestCase):
2023 """
2024 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
2025 """
2026 def test_construction(self):
2027 """
2028 :py:class:`Session` can be constructed with no arguments, creating a new
2029 instance of that type.
2030 """
2031 new_session = Session()
2032 self.assertTrue(isinstance(new_session, Session))
2033
2034
2035 def test_construction_wrong_args(self):
2036 """
2037 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
2038 is raised.
2039 """
2040 self.assertRaises(TypeError, Session, 123)
2041 self.assertRaises(TypeError, Session, "hello")
2042 self.assertRaises(TypeError, Session, object())
2043
2044
2045
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002046class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05002047 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002048 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002049 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002050 # XXX get_peer_certificate -> None
2051 # XXX sock_shutdown
2052 # XXX master_key -> TypeError
2053 # XXX server_random -> TypeError
2054 # XXX state_string
2055 # XXX connect -> TypeError
2056 # XXX connect_ex -> TypeError
2057 # XXX set_connect_state -> TypeError
2058 # XXX set_accept_state -> TypeError
2059 # XXX renegotiate_pending
2060 # XXX do_handshake -> TypeError
2061 # XXX bio_read -> TypeError
2062 # XXX recv -> TypeError
2063 # XXX send -> TypeError
2064 # XXX bio_write -> TypeError
2065
Rick Deane15b1472009-07-09 15:53:42 -05002066 def test_type(self):
2067 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002068 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002069 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002070 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002071 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05002072 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002073 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002074
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002075
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002076 def test_get_context(self):
2077 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002078 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
2079 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002080 """
2081 context = Context(TLSv1_METHOD)
2082 connection = Connection(context, None)
2083 self.assertIdentical(connection.get_context(), context)
2084
2085
2086 def test_get_context_wrong_args(self):
2087 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002088 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002089 arguments.
2090 """
2091 connection = Connection(Context(TLSv1_METHOD), None)
2092 self.assertRaises(TypeError, connection.get_context, None)
2093
2094
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002095 def test_set_context_wrong_args(self):
2096 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002097 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
2098 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002099 than 1.
2100 """
2101 ctx = Context(TLSv1_METHOD)
2102 connection = Connection(ctx, None)
2103 self.assertRaises(TypeError, connection.set_context)
2104 self.assertRaises(TypeError, connection.set_context, object())
2105 self.assertRaises(TypeError, connection.set_context, "hello")
2106 self.assertRaises(TypeError, connection.set_context, 1)
2107 self.assertRaises(TypeError, connection.set_context, 1, 2)
2108 self.assertRaises(
2109 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
2110 self.assertIdentical(ctx, connection.get_context())
2111
2112
2113 def test_set_context(self):
2114 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002115 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002116 for the connection.
2117 """
2118 original = Context(SSLv23_METHOD)
2119 replacement = Context(TLSv1_METHOD)
2120 connection = Connection(original, None)
2121 connection.set_context(replacement)
2122 self.assertIdentical(replacement, connection.get_context())
2123 # Lose our references to the contexts, just in case the Connection isn't
2124 # properly managing its own contributions to their reference counts.
2125 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002126 collect()
2127
2128
2129 def test_set_tlsext_host_name_wrong_args(self):
2130 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002131 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002132 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09002133 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002134 """
2135 conn = Connection(Context(TLSv1_METHOD), None)
2136 self.assertRaises(TypeError, conn.set_tlsext_host_name)
2137 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
2138 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
2139 self.assertRaises(
2140 TypeError, conn.set_tlsext_host_name, b("with\0null"))
2141
Abraham Martinc5484ba2015-03-25 15:33:05 +00002142 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002143 # On Python 3.x, don't accidentally implicitly convert from text.
2144 self.assertRaises(
2145 TypeError,
2146 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002147
2148
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002149 def test_get_servername_wrong_args(self):
2150 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002151 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002152 arguments.
2153 """
2154 connection = Connection(Context(TLSv1_METHOD), None)
2155 self.assertRaises(TypeError, connection.get_servername, object())
2156 self.assertRaises(TypeError, connection.get_servername, 1)
2157 self.assertRaises(TypeError, connection.get_servername, "hello")
2158
2159
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002160 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002161 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002162 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002163 immediate read.
2164 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002165 connection = Connection(Context(TLSv1_METHOD), None)
2166 self.assertEquals(connection.pending(), 0)
2167
2168
2169 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002170 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002171 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002172 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002173 connection = Connection(Context(TLSv1_METHOD), None)
2174 self.assertRaises(TypeError, connection.pending, None)
2175
2176
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002177 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002178 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002179 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002180 argument or with the wrong number of arguments.
2181 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002182 connection = Connection(Context(TLSv1_METHOD), socket())
2183 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002184 self.assertRaises(TypeError, connection.connect)
2185 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002186
2187
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002188 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002189 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002190 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002191 connect method raises it.
2192 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002193 client = socket()
2194 context = Context(TLSv1_METHOD)
2195 clientSSL = Connection(context, client)
2196 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04002197 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002198
2199
2200 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002201 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002202 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002203 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002204 port = socket()
2205 port.bind(('', 0))
2206 port.listen(3)
2207
2208 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002209 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2210 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002211
2212
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002213 if platform == "darwin":
2214 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2215 else:
2216 def test_connect_ex(self):
2217 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002218 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002219 errno instead of raising an exception.
2220 """
2221 port = socket()
2222 port.bind(('', 0))
2223 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002224
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002225 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2226 clientSSL.setblocking(False)
2227 result = clientSSL.connect_ex(port.getsockname())
2228 expected = (EINPROGRESS, EWOULDBLOCK)
2229 self.assertTrue(
2230 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002231
2232
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002233 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002234 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002235 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002236 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002237 connection = Connection(Context(TLSv1_METHOD), socket())
2238 self.assertRaises(TypeError, connection.accept, None)
2239
2240
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002241 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002242 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002243 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
2244 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002245 connection originated from.
2246 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002247 ctx = Context(TLSv1_METHOD)
2248 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2249 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002250 port = socket()
2251 portSSL = Connection(ctx, port)
2252 portSSL.bind(('', 0))
2253 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002254
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002255 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002256
2257 # Calling portSSL.getsockname() here to get the server IP address sounds
2258 # great, but frequently fails on Windows.
2259 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002260
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002261 serverSSL, address = portSSL.accept()
2262
2263 self.assertTrue(isinstance(serverSSL, Connection))
2264 self.assertIdentical(serverSSL.get_context(), ctx)
2265 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002266
2267
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002268 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002269 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002270 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002271 number of arguments or with arguments other than integers.
2272 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002273 connection = Connection(Context(TLSv1_METHOD), None)
2274 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04002275 self.assertRaises(TypeError, connection.get_shutdown, None)
2276 self.assertRaises(TypeError, connection.set_shutdown)
2277 self.assertRaises(TypeError, connection.set_shutdown, None)
2278 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002279
2280
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002281 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002282 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002283 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002284 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002285 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002286 self.assertFalse(server.shutdown())
2287 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002288 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002289 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
2290 client.shutdown()
2291 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
2292 self.assertRaises(ZeroReturnError, server.recv, 1024)
2293 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002294
2295
Paul Aurichc85e0862015-01-08 08:34:33 -08002296 def test_shutdown_closed(self):
2297 """
2298 If the underlying socket is closed, :py:obj:`Connection.shutdown` propagates the
2299 write error from the low level write call.
2300 """
2301 server, client = self._loopback()
2302 server.sock_shutdown(2)
2303 exc = self.assertRaises(SysCallError, server.shutdown)
2304 if platform == "win32":
2305 self.assertEqual(exc.args[0], ESHUTDOWN)
2306 else:
2307 self.assertEqual(exc.args[0], EPIPE)
2308
2309
Glyph89389472015-04-14 17:29:26 -04002310 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002311 """
Glyph89389472015-04-14 17:29:26 -04002312 If the underlying connection is truncated, :obj:`Connection.shutdown`
2313 raises an :obj:`Error`.
Glyph6064ec32015-04-14 16:38:22 -04002314 """
Glyph89389472015-04-14 17:29:26 -04002315 server_ctx = Context(TLSv1_METHOD)
2316 client_ctx = Context(TLSv1_METHOD)
2317 server_ctx.use_privatekey(
2318 load_privatekey(FILETYPE_PEM, server_key_pem))
2319 server_ctx.use_certificate(
2320 load_certificate(FILETYPE_PEM, server_cert_pem))
2321 server = Connection(server_ctx, None)
2322 client = Connection(client_ctx, None)
2323 self._handshakeInMemory(client, server)
2324 self.assertEqual(server.shutdown(), False)
2325 self.assertRaises(WantReadError, server.shutdown)
2326 server.bio_shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002327 self.assertRaises(Error, server.shutdown)
2328
2329
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002330 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002331 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002332 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002333 process.
2334 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002335 connection = Connection(Context(TLSv1_METHOD), socket())
2336 connection.set_shutdown(RECEIVED_SHUTDOWN)
2337 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2338
2339
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002340 if not PY3:
2341 def test_set_shutdown_long(self):
2342 """
2343 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
2344 of type :py:obj:`long` as well as :py:obj:`int`.
2345 """
2346 connection = Connection(Context(TLSv1_METHOD), socket())
2347 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
2348 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2349
2350
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002351 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002352 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002353 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
2354 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002355 with any arguments.
2356 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002357 conn = Connection(Context(TLSv1_METHOD), None)
2358 self.assertRaises(TypeError, conn.get_app_data, None)
2359 self.assertRaises(TypeError, conn.set_app_data)
2360 self.assertRaises(TypeError, conn.set_app_data, None, None)
2361
2362
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002363 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002364 """
2365 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002366 :py:obj:`Connection.set_app_data` and later retrieved with
2367 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002368 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002369 conn = Connection(Context(TLSv1_METHOD), None)
2370 app_data = object()
2371 conn.set_app_data(app_data)
2372 self.assertIdentical(conn.get_app_data(), app_data)
2373
2374
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002375 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002376 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002377 :py:obj:`Connection.makefile` is not implemented and calling that method raises
2378 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002379 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002380 conn = Connection(Context(TLSv1_METHOD), None)
2381 self.assertRaises(NotImplementedError, conn.makefile)
2382
2383
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002384 def test_get_peer_cert_chain_wrong_args(self):
2385 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002386 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002387 arguments.
2388 """
2389 conn = Connection(Context(TLSv1_METHOD), None)
2390 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
2391 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
2392 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
2393 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
2394
2395
2396 def test_get_peer_cert_chain(self):
2397 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002398 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002399 the connected server returned for the certification verification.
2400 """
2401 chain = _create_certificate_chain()
2402 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2403
2404 serverContext = Context(TLSv1_METHOD)
2405 serverContext.use_privatekey(skey)
2406 serverContext.use_certificate(scert)
2407 serverContext.add_extra_chain_cert(icert)
2408 serverContext.add_extra_chain_cert(cacert)
2409 server = Connection(serverContext, None)
2410 server.set_accept_state()
2411
2412 # Create the client
2413 clientContext = Context(TLSv1_METHOD)
2414 clientContext.set_verify(VERIFY_NONE, verify_cb)
2415 client = Connection(clientContext, None)
2416 client.set_connect_state()
2417
2418 self._interactInMemory(client, server)
2419
2420 chain = client.get_peer_cert_chain()
2421 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002422 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002423 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002424 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002425 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002426 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002427 "Authority Certificate", chain[2].get_subject().CN)
2428
2429
2430 def test_get_peer_cert_chain_none(self):
2431 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002432 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002433 certificate chain.
2434 """
2435 ctx = Context(TLSv1_METHOD)
2436 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2437 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2438 server = Connection(ctx, None)
2439 server.set_accept_state()
2440 client = Connection(Context(TLSv1_METHOD), None)
2441 client.set_connect_state()
2442 self._interactInMemory(client, server)
2443 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002444
2445
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002446 def test_get_session_wrong_args(self):
2447 """
2448 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
2449 with any arguments.
2450 """
2451 ctx = Context(TLSv1_METHOD)
2452 server = Connection(ctx, None)
2453 self.assertRaises(TypeError, server.get_session, 123)
2454 self.assertRaises(TypeError, server.get_session, "hello")
2455 self.assertRaises(TypeError, server.get_session, object())
2456
2457
2458 def test_get_session_unconnected(self):
2459 """
2460 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
2461 an object which has not been connected.
2462 """
2463 ctx = Context(TLSv1_METHOD)
2464 server = Connection(ctx, None)
2465 session = server.get_session()
2466 self.assertIdentical(None, session)
2467
2468
2469 def test_server_get_session(self):
2470 """
2471 On the server side of a connection, :py:obj:`Connection.get_session`
2472 returns a :py:class:`Session` instance representing the SSL session for
2473 that connection.
2474 """
2475 server, client = self._loopback()
2476 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002477 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002478
2479
2480 def test_client_get_session(self):
2481 """
2482 On the client side of a connection, :py:obj:`Connection.get_session`
2483 returns a :py:class:`Session` instance representing the SSL session for
2484 that connection.
2485 """
2486 server, client = self._loopback()
2487 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002488 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002489
2490
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002491 def test_set_session_wrong_args(self):
2492 """
2493 If called with an object that is not an instance of :py:class:`Session`,
2494 or with other than one argument, :py:obj:`Connection.set_session` raises
2495 :py:obj:`TypeError`.
2496 """
2497 ctx = Context(TLSv1_METHOD)
2498 connection = Connection(ctx, None)
2499 self.assertRaises(TypeError, connection.set_session)
2500 self.assertRaises(TypeError, connection.set_session, 123)
2501 self.assertRaises(TypeError, connection.set_session, "hello")
2502 self.assertRaises(TypeError, connection.set_session, object())
2503 self.assertRaises(
2504 TypeError, connection.set_session, Session(), Session())
2505
2506
2507 def test_client_set_session(self):
2508 """
2509 :py:obj:`Connection.set_session`, when used prior to a connection being
2510 established, accepts a :py:class:`Session` instance and causes an
2511 attempt to re-use the session it represents when the SSL handshake is
2512 performed.
2513 """
2514 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2515 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2516 ctx = Context(TLSv1_METHOD)
2517 ctx.use_privatekey(key)
2518 ctx.use_certificate(cert)
2519 ctx.set_session_id("unity-test")
2520
2521 def makeServer(socket):
2522 server = Connection(ctx, socket)
2523 server.set_accept_state()
2524 return server
2525
2526 originalServer, originalClient = self._loopback(
2527 serverFactory=makeServer)
2528 originalSession = originalClient.get_session()
2529
2530 def makeClient(socket):
2531 client = self._loopbackClientFactory(socket)
2532 client.set_session(originalSession)
2533 return client
2534 resumedServer, resumedClient = self._loopback(
2535 serverFactory=makeServer,
2536 clientFactory=makeClient)
2537
2538 # This is a proxy: in general, we have no access to any unique
2539 # identifier for the session (new enough versions of OpenSSL expose a
2540 # hash which could be usable, but "new enough" is very, very new).
2541 # Instead, exploit the fact that the master key is re-used if the
2542 # session is re-used. As long as the master key for the two connections
2543 # is the same, the session was re-used!
2544 self.assertEqual(
2545 originalServer.master_key(), resumedServer.master_key())
2546
2547
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002548 def test_set_session_wrong_method(self):
2549 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002550 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
2551 instance associated with a context using a different SSL method than the
2552 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
2553 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002554 """
2555 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2556 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2557 ctx = Context(TLSv1_METHOD)
2558 ctx.use_privatekey(key)
2559 ctx.use_certificate(cert)
2560 ctx.set_session_id("unity-test")
2561
2562 def makeServer(socket):
2563 server = Connection(ctx, socket)
2564 server.set_accept_state()
2565 return server
2566
2567 originalServer, originalClient = self._loopback(
2568 serverFactory=makeServer)
2569 originalSession = originalClient.get_session()
2570
2571 def makeClient(socket):
2572 # Intentionally use a different, incompatible method here.
2573 client = Connection(Context(SSLv3_METHOD), socket)
2574 client.set_connect_state()
2575 client.set_session(originalSession)
2576 return client
2577
2578 self.assertRaises(
2579 Error,
2580 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2581
2582
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002583 def test_wantWriteError(self):
2584 """
2585 :py:obj:`Connection` methods which generate output raise
2586 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2587 fail indicating a should-write state.
2588 """
2589 client_socket, server_socket = socket_pair()
2590 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002591 # anything. Only write a single byte at a time so we can be sure we
2592 # completely fill the buffer. Even though the socket API is allowed to
2593 # signal a short write via its return value it seems this doesn't
2594 # always happen on all platforms (FreeBSD and OS X particular) for the
2595 # very last bit of available buffer space.
2596 msg = b"x"
2597 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002598 try:
2599 client_socket.send(msg)
2600 except error as e:
2601 if e.errno == EWOULDBLOCK:
2602 break
2603 raise
2604 else:
2605 self.fail(
2606 "Failed to fill socket buffer, cannot test BIO want write")
2607
2608 ctx = Context(TLSv1_METHOD)
2609 conn = Connection(ctx, client_socket)
2610 # Client's speak first, so make it an SSL client
2611 conn.set_connect_state()
2612 self.assertRaises(WantWriteError, conn.do_handshake)
2613
2614 # XXX want_read
2615
Fedor Brunner416f4a12014-03-28 13:18:38 +01002616 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002617 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002618 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2619 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002620 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002621 ctx = Context(TLSv1_METHOD)
2622 connection = Connection(ctx, None)
2623 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002624
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002625
Fedor Brunner416f4a12014-03-28 13:18:38 +01002626 def test_get_peer_finished_before_connect(self):
2627 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002628 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2629 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002630 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002631 ctx = Context(TLSv1_METHOD)
2632 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002633 self.assertEqual(connection.get_peer_finished(), None)
2634
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002635
Fedor Brunner416f4a12014-03-28 13:18:38 +01002636 def test_get_finished(self):
2637 """
2638 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002639 message send from client, or server. Finished messages are send during
2640 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002641 """
2642
Fedor Brunner5747b932014-03-05 14:22:34 +01002643 server, client = self._loopback()
2644
2645 self.assertNotEqual(server.get_finished(), None)
2646 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002647
Jean-Paul Calderoned979f232014-03-30 11:58:00 -04002648
Fedor Brunner416f4a12014-03-28 13:18:38 +01002649 def test_get_peer_finished(self):
2650 """
2651 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002652 message received from client, or server. Finished messages are send
2653 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002654 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002655 server, client = self._loopback()
2656
2657 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002658 self.assertTrue(len(server.get_peer_finished()) > 0)
2659
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002660
Fedor Brunner416f4a12014-03-28 13:18:38 +01002661 def test_tls_finished_message_symmetry(self):
2662 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002663 The TLS Finished message send by server must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002664 received by client.
2665
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002666 The TLS Finished message send by client must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002667 received by server.
2668 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002669 server, client = self._loopback()
2670
Fedor Brunner5747b932014-03-05 14:22:34 +01002671 self.assertEqual(server.get_finished(), client.get_peer_finished())
2672 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002673
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002674
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002675 def test_get_cipher_name_before_connect(self):
2676 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002677 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2678 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002679 """
2680 ctx = Context(TLSv1_METHOD)
2681 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002682 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002683
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002684
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002685 def test_get_cipher_name(self):
2686 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002687 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2688 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002689 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002690 server, client = self._loopback()
2691 server_cipher_name, client_cipher_name = \
2692 server.get_cipher_name(), client.get_cipher_name()
2693
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002694 self.assertIsInstance(server_cipher_name, text_type)
2695 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002696
2697 self.assertEqual(server_cipher_name, client_cipher_name)
2698
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002699
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002700 def test_get_cipher_version_before_connect(self):
2701 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002702 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2703 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002704 """
2705 ctx = Context(TLSv1_METHOD)
2706 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002707 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002708
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002709
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002710 def test_get_cipher_version(self):
2711 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002712 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2713 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002714 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002715 server, client = self._loopback()
2716 server_cipher_version, client_cipher_version = \
2717 server.get_cipher_version(), client.get_cipher_version()
2718
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002719 self.assertIsInstance(server_cipher_version, text_type)
2720 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002721
2722 self.assertEqual(server_cipher_version, client_cipher_version)
2723
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002724
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002725 def test_get_cipher_bits_before_connect(self):
2726 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002727 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2728 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002729 """
2730 ctx = Context(TLSv1_METHOD)
2731 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002732 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002733
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002734
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002735 def test_get_cipher_bits(self):
2736 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002737 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2738 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002739 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002740 server, client = self._loopback()
2741 server_cipher_bits, client_cipher_bits = \
2742 server.get_cipher_bits(), client.get_cipher_bits()
2743
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002744 self.assertIsInstance(server_cipher_bits, int)
2745 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002746
2747 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002748
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002749
2750
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002751class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002752 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002753 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002754 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002755 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002756 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002757 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002758 arguments.
2759 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002760 connection = Connection(Context(TLSv1_METHOD), None)
2761 self.assertRaises(TypeError, connection.get_cipher_list, None)
2762
2763
2764 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002765 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002766 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2767 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002768 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002769 connection = Connection(Context(TLSv1_METHOD), None)
2770 ciphers = connection.get_cipher_list()
2771 self.assertTrue(isinstance(ciphers, list))
2772 for cipher in ciphers:
2773 self.assertTrue(isinstance(cipher, str))
2774
2775
2776
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002777class ConnectionSendTests(TestCase, _LoopbackMixin):
2778 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002779 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002780 """
2781 def test_wrong_args(self):
2782 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002783 When called with arguments other than string argument for its first
2784 parameter or more than two arguments, :py:obj:`Connection.send` raises
2785 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002786 """
2787 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002788 self.assertRaises(TypeError, connection.send)
2789 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002790 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002791
2792
2793 def test_short_bytes(self):
2794 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002795 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002796 and returns the number of bytes sent.
2797 """
2798 server, client = self._loopback()
2799 count = server.send(b('xy'))
2800 self.assertEquals(count, 2)
2801 self.assertEquals(client.recv(2), b('xy'))
2802
Abraham Martinef063482015-03-25 14:06:24 +00002803
2804 def test_text(self):
2805 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002806 When passed a text, :py:obj:`Connection.send` transmits all of it and
2807 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002808 """
2809 server, client = self._loopback()
2810 with catch_warnings(record=True) as w:
2811 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002812 count = server.send(b"xy".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002813 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002814 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002815 WARNING_TYPE_EXPECTED
2816 ),
2817 str(w[-1].message)
2818 )
2819 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinef063482015-03-25 14:06:24 +00002820 self.assertEquals(count, 2)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002821 self.assertEquals(client.recv(2), b"xy")
Abraham Martinef063482015-03-25 14:06:24 +00002822
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002823 try:
2824 memoryview
2825 except NameError:
2826 "cannot test sending memoryview without memoryview"
2827 else:
2828 def test_short_memoryview(self):
2829 """
2830 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002831 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002832 bytes sent.
2833 """
2834 server, client = self._loopback()
2835 count = server.send(memoryview(b('xy')))
2836 self.assertEquals(count, 2)
2837 self.assertEquals(client.recv(2), b('xy'))
2838
2839
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002840 try:
2841 buffer
2842 except NameError:
2843 "cannot test sending buffer without buffer"
2844 else:
2845 def test_short_buffer(self):
2846 """
2847 When passed a buffer containing a small number of bytes,
2848 :py:obj:`Connection.send` transmits all of them and returns the number of
2849 bytes sent.
2850 """
2851 server, client = self._loopback()
2852 count = server.send(buffer(b('xy')))
2853 self.assertEquals(count, 2)
2854 self.assertEquals(client.recv(2), b('xy'))
2855
2856
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002857
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002858def _make_memoryview(size):
2859 """
2860 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2861 size.
2862 """
2863 return memoryview(bytearray(size))
2864
2865
2866
Cory Benfield62d10332014-06-15 10:03:41 +01002867class ConnectionRecvIntoTests(TestCase, _LoopbackMixin):
2868 """
2869 Tests for :py:obj:`Connection.recv_into`
2870 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002871 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002872 """
2873 Assert that when the given buffer is passed to
2874 ``Connection.recv_into``, whatever bytes are available to be received
2875 that fit into that buffer are written into that buffer.
2876 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002877 output_buffer = factory(5)
2878
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002879 server, client = self._loopback()
2880 server.send(b('xy'))
2881
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002882 self.assertEqual(client.recv_into(output_buffer), 2)
2883 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002884
2885
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002886 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002887 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002888 :py:obj:`Connection.recv_into` can be passed a ``bytearray`` instance
2889 and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002890 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002891 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002892
2893
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002894 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002895 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002896 Assert that when the given buffer is passed to ``Connection.recv_into``
2897 along with a value for ``nbytes`` that is less than the size of that
2898 buffer, only ``nbytes`` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002899 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002900 output_buffer = factory(10)
2901
Cory Benfield62d10332014-06-15 10:03:41 +01002902 server, client = self._loopback()
2903 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002904
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002905 self.assertEqual(client.recv_into(output_buffer, 5), 5)
2906 self.assertEqual(
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002907 output_buffer, bytearray(b('abcde\x00\x00\x00\x00\x00'))
2908 )
2909
2910
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002911 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002912 """
2913 When called with a ``bytearray`` instance,
2914 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter and
2915 doesn't copy in more than that number of bytes.
2916 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002917 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002918
2919
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002920 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002921 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002922 Assert that if there are more bytes available to be read from the
2923 receive buffer than would fit into the buffer passed to
2924 :py:obj:`Connection.recv_into`, only as many as fit are written into
2925 it.
Cory Benfield62d10332014-06-15 10:03:41 +01002926 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002927 output_buffer = factory(5)
2928
Cory Benfield62d10332014-06-15 10:03:41 +01002929 server, client = self._loopback()
2930 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002931
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002932 self.assertEqual(client.recv_into(output_buffer), 5)
2933 self.assertEqual(output_buffer, bytearray(b('abcde')))
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002934 rest = client.recv(5)
2935 self.assertEqual(b('fghij'), rest)
2936
2937
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002938 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002939 """
2940 When called with a ``bytearray`` instance,
2941 :py:obj:`Connection.recv_into` respects the size of the array and
2942 doesn't write more bytes into it than will fit.
2943 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002944 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002945
2946
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002947 def _really_doesnt_overfill_test(self, factory):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002948 """
2949 Assert that if the value given by ``nbytes`` is greater than the actual
2950 size of the output buffer passed to :py:obj:`Connection.recv_into`, the
2951 behavior is as if no value was given for ``nbytes`` at all.
2952 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002953 output_buffer = factory(5)
2954
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002955 server, client = self._loopback()
2956 server.send(b('abcdefghij'))
2957
2958 self.assertEqual(client.recv_into(output_buffer, 50), 5)
2959 self.assertEqual(output_buffer, bytearray(b('abcde')))
2960 rest = client.recv(5)
2961 self.assertEqual(b('fghij'), rest)
2962
2963
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002964 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002965 """
2966 When called with a ``bytearray`` instance and an ``nbytes`` value that
2967 is too large, :py:obj:`Connection.recv_into` respects the size of the
2968 array and not the ``nbytes`` value and doesn't write more bytes into
2969 the buffer than will fit.
2970 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002971 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002972
2973
Cory Benfield62d10332014-06-15 10:03:41 +01002974 try:
2975 memoryview
2976 except NameError:
2977 "cannot test recv_into memoryview without memoryview"
2978 else:
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002979 def test_memoryview_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002980 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002981 :py:obj:`Connection.recv_into` can be passed a ``memoryview``
2982 instance and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002983 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002984 self._no_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002985
2986
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002987 def test_memoryview_respects_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002988 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002989 When called with a ``memoryview`` instance,
2990 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter
2991 and doesn't copy more than that number of bytes in.
Cory Benfield62d10332014-06-15 10:03:41 +01002992 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002993 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002994
2995
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002996 def test_memoryview_doesnt_overfill(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002997 """
Jean-Paul Calderone8fd82552015-03-15 17:21:07 -04002998 When called with a ``memoryview`` instance,
2999 :py:obj:`Connection.recv_into` respects the size of the array and
3000 doesn't write more bytes into it than will fit.
Cory Benfield62d10332014-06-15 10:03:41 +01003001 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003002 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003003
3004
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003005 def test_memoryview_really_doesnt_overfill(self):
3006 """
3007 When called with a ``memoryview`` instance and an ``nbytes`` value
3008 that is too large, :py:obj:`Connection.recv_into` respects the size
3009 of the array and not the ``nbytes`` value and doesn't write more
3010 bytes into the buffer than will fit.
3011 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003012 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003013
3014
Cory Benfield62d10332014-06-15 10:03:41 +01003015
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003016class ConnectionSendallTests(TestCase, _LoopbackMixin):
3017 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003018 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003019 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003020 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003021 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003022 When called with arguments other than a string argument for its first
3023 parameter or with more than two arguments, :py:obj:`Connection.sendall`
3024 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003025 """
3026 connection = Connection(Context(TLSv1_METHOD), None)
3027 self.assertRaises(TypeError, connection.sendall)
3028 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003029 self.assertRaises(
3030 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003031
3032
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003033 def test_short(self):
3034 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003035 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003036 it.
3037 """
3038 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04003039 server.sendall(b('x'))
3040 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003041
3042
Abraham Martinef063482015-03-25 14:06:24 +00003043 def test_text(self):
3044 """
Jean-Paul Calderone93477422015-04-13 20:38:57 -04003045 :py:obj:`Connection.sendall` transmits all the content in the string
3046 passed to it raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003047 """
3048 server, client = self._loopback()
3049 with catch_warnings(record=True) as w:
3050 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003051 server.sendall(b"x".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003052 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003053 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003054 WARNING_TYPE_EXPECTED
3055 ),
3056 str(w[-1].message)
3057 )
3058 self.assertIs(w[-1].category, DeprecationWarning)
3059 self.assertEquals(client.recv(1), b"x")
Abraham Martinef063482015-03-25 14:06:24 +00003060
3061
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003062 try:
3063 memoryview
3064 except NameError:
3065 "cannot test sending memoryview without memoryview"
3066 else:
3067 def test_short_memoryview(self):
3068 """
3069 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003070 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003071 """
3072 server, client = self._loopback()
3073 server.sendall(memoryview(b('x')))
3074 self.assertEquals(client.recv(1), b('x'))
3075
3076
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003077 try:
3078 buffer
3079 except NameError:
3080 "cannot test sending buffers without buffers"
3081 else:
3082 def test_short_buffers(self):
3083 """
3084 When passed a buffer containing a small number of bytes,
3085 :py:obj:`Connection.sendall` transmits all of them.
3086 """
3087 server, client = self._loopback()
3088 server.sendall(buffer(b('x')))
3089 self.assertEquals(client.recv(1), b('x'))
3090
3091
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003092 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003093 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003094 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003095 it even if this requires multiple calls of an underlying write function.
3096 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003097 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003098 # Should be enough, underlying SSL_write should only do 16k at a time.
3099 # On Windows, after 32k of bytes the write will block (forever - because
3100 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04003101 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003102 server.sendall(message)
3103 accum = []
3104 received = 0
3105 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003106 data = client.recv(1024)
3107 accum.append(data)
3108 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04003109 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003110
3111
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003112 def test_closed(self):
3113 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003114 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003115 write error from the low level write call.
3116 """
3117 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003118 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003119 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003120 if platform == "win32":
3121 self.assertEqual(exc.args[0], ESHUTDOWN)
3122 else:
3123 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003124
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003125
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04003126
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003127class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
3128 """
3129 Tests for SSL renegotiation APIs.
3130 """
3131 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003132 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003133 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003134 arguments.
3135 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003136 connection = Connection(Context(TLSv1_METHOD), None)
3137 self.assertRaises(TypeError, connection.renegotiate, None)
3138
3139
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003140 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003141 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003142 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003143 any arguments.
3144 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003145 connection = Connection(Context(TLSv1_METHOD), None)
3146 self.assertRaises(TypeError, connection.total_renegotiations, None)
3147
3148
3149 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003150 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003151 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003152 renegotiations have happened.
3153 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003154 connection = Connection(Context(TLSv1_METHOD), None)
3155 self.assertEquals(connection.total_renegotiations(), 0)
3156
3157
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003158# def test_renegotiate(self):
3159# """
3160# """
3161# server, client = self._loopback()
3162
3163# server.send("hello world")
3164# self.assertEquals(client.recv(len("hello world")), "hello world")
3165
3166# self.assertEquals(server.total_renegotiations(), 0)
3167# self.assertTrue(server.renegotiate())
3168
3169# server.setblocking(False)
3170# client.setblocking(False)
3171# while server.renegotiate_pending():
3172# client.do_handshake()
3173# server.do_handshake()
3174
3175# self.assertEquals(server.total_renegotiations(), 1)
3176
3177
3178
3179
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003180class ErrorTests(TestCase):
3181 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003182 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003183 """
3184 def test_type(self):
3185 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003186 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003187 """
3188 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05003189 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05003190
3191
3192
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003193class ConstantsTests(TestCase):
3194 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003195 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003196
3197 These are values defined by OpenSSL intended only to be used as flags to
3198 OpenSSL APIs. The only assertions it seems can be made about them is
3199 their values.
3200 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003201 # unittest.TestCase has no skip mechanism
3202 if OP_NO_QUERY_MTU is not None:
3203 def test_op_no_query_mtu(self):
3204 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003205 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003206 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003207 """
3208 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
3209 else:
3210 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003211
3212
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003213 if OP_COOKIE_EXCHANGE is not None:
3214 def test_op_cookie_exchange(self):
3215 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003216 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003217 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003218 """
3219 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
3220 else:
3221 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003222
3223
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003224 if OP_NO_TICKET is not None:
3225 def test_op_no_ticket(self):
3226 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003227 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003228 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003229 """
3230 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04003231 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003232 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05003233
3234
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003235 if OP_NO_COMPRESSION is not None:
3236 def test_op_no_compression(self):
3237 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003238 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
3239 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003240 """
3241 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
3242 else:
3243 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3244
3245
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003246 def test_sess_cache_off(self):
3247 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003248 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3249 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003250 """
3251 self.assertEqual(0x0, SESS_CACHE_OFF)
3252
3253
3254 def test_sess_cache_client(self):
3255 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003256 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3257 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003258 """
3259 self.assertEqual(0x1, SESS_CACHE_CLIENT)
3260
3261
3262 def test_sess_cache_server(self):
3263 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003264 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3265 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003266 """
3267 self.assertEqual(0x2, SESS_CACHE_SERVER)
3268
3269
3270 def test_sess_cache_both(self):
3271 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003272 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3273 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003274 """
3275 self.assertEqual(0x3, SESS_CACHE_BOTH)
3276
3277
3278 def test_sess_cache_no_auto_clear(self):
3279 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003280 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3281 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3282 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003283 """
3284 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
3285
3286
3287 def test_sess_cache_no_internal_lookup(self):
3288 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003289 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3290 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3291 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003292 """
3293 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
3294
3295
3296 def test_sess_cache_no_internal_store(self):
3297 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003298 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3299 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3300 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003301 """
3302 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
3303
3304
3305 def test_sess_cache_no_internal(self):
3306 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003307 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3308 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
3309 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003310 """
3311 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
3312
3313
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04003314
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003315class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05003316 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003317 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003318 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003319 def _server(self, sock):
3320 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003321 Create a new server-side SSL :py:obj:`Connection` object wrapped around
3322 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003323 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003324 # Create the server side Connection. This is mostly setup boilerplate
3325 # - use TLSv1, use a particular certificate, etc.
3326 server_ctx = Context(TLSv1_METHOD)
3327 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
3328 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
3329 server_store = server_ctx.get_cert_store()
3330 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3331 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3332 server_ctx.check_privatekey()
3333 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003334 # Here the Connection is actually created. If None is passed as the 2nd
3335 # parameter, it indicates a memory BIO should be created.
3336 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003337 server_conn.set_accept_state()
3338 return server_conn
3339
3340
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003341 def _client(self, sock):
3342 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003343 Create a new client-side SSL :py:obj:`Connection` object wrapped around
3344 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003345 """
3346 # Now create the client side Connection. Similar boilerplate to the
3347 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003348 client_ctx = Context(TLSv1_METHOD)
3349 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
3350 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
3351 client_store = client_ctx.get_cert_store()
3352 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
3353 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
3354 client_ctx.check_privatekey()
3355 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003356 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003357 client_conn.set_connect_state()
3358 return client_conn
3359
3360
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003361 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003362 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003363 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003364 reading from the output of each and writing those bytes to the input of
3365 the other and in this way establish a connection and exchange
3366 application-level bytes with each other.
3367 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003368 server_conn = self._server(None)
3369 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003370
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003371 # There should be no key or nonces yet.
3372 self.assertIdentical(server_conn.master_key(), None)
3373 self.assertIdentical(server_conn.client_random(), None)
3374 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003375
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003376 # First, the handshake needs to happen. We'll deliver bytes back and
3377 # forth between the client and server until neither of them feels like
3378 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003379 self.assertIdentical(
3380 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003381
3382 # Now that the handshake is done, there should be a key and nonces.
3383 self.assertNotIdentical(server_conn.master_key(), None)
3384 self.assertNotIdentical(server_conn.client_random(), None)
3385 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04003386 self.assertEquals(server_conn.client_random(), client_conn.client_random())
3387 self.assertEquals(server_conn.server_random(), client_conn.server_random())
3388 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
3389 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003390
3391 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003392 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05003393
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003394 server_conn.write(important_message)
3395 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003396 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003397 (client_conn, important_message))
3398
3399 client_conn.write(important_message[::-1])
3400 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003401 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003402 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003403
3404
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003405 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003406 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003407 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003408
3409 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09003410 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003411 this test fails, there must be a problem outside the memory BIO
3412 code, as no memory BIO is involved here). Even though this isn't a
3413 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003414 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04003415 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003416
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003417 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05003418 client_conn.send(important_message)
3419 msg = server_conn.recv(1024)
3420 self.assertEqual(msg, important_message)
3421
3422 # Again in the other direction, just for fun.
3423 important_message = important_message[::-1]
3424 server_conn.send(important_message)
3425 msg = client_conn.recv(1024)
3426 self.assertEqual(msg, important_message)
3427
3428
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04003429 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003430 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003431 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
3432 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003433 """
3434 context = Context(SSLv3_METHOD)
3435 client = socket()
3436 clientSSL = Connection(context, client)
3437 self.assertRaises( TypeError, clientSSL.bio_read, 100)
3438 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04003439 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003440
3441
3442 def test_outgoingOverflow(self):
3443 """
3444 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09003445 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003446 returned and that many bytes from the beginning of the input can be
3447 read from the other end of the connection.
3448 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003449 server = self._server(None)
3450 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003451
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003452 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003453
3454 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003455 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003456 # Sanity check. We're trying to test what happens when the entire
3457 # input can't be sent. If the entire input was sent, this test is
3458 # meaningless.
3459 self.assertTrue(sent < size)
3460
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003461 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003462 self.assertIdentical(receiver, server)
3463
3464 # We can rely on all of these bytes being received at once because
3465 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
3466 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003467
3468
3469 def test_shutdown(self):
3470 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003471 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
3472 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003473 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003474 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003475 server.bio_shutdown()
3476 e = self.assertRaises(Error, server.recv, 1024)
3477 # We don't want WantReadError or ZeroReturnError or anything - it's a
3478 # handshake failure.
3479 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003480
3481
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003482 def test_unexpectedEndOfFile(self):
3483 """
3484 If the connection is lost before an orderly SSL shutdown occurs,
3485 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
3486 "Unexpected EOF".
3487 """
3488 server_conn, client_conn = self._loopback()
3489 client_conn.sock_shutdown(SHUT_RDWR)
3490 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
3491 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
3492
3493
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003494 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003495 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003496 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 -04003497
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003498 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003499 before the client and server are connected to each other. This
3500 function should specify a list of CAs for the server to send to the
3501 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09003502 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003503 times.
3504 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003505 server = self._server(None)
3506 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003507 self.assertEqual(client.get_client_ca_list(), [])
3508 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003509 ctx = server.get_context()
3510 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003511 self.assertEqual(client.get_client_ca_list(), [])
3512 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003513 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003514 self.assertEqual(client.get_client_ca_list(), expected)
3515 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003516
3517
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003518 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003519 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003520 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003521 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003522 """
3523 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003524 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
3525 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
3526 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003527
3528
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003529 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003530 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003531 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003532 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09003533 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003534 after the connection is set up.
3535 """
3536 def no_ca(ctx):
3537 ctx.set_client_ca_list([])
3538 return []
3539 self._check_client_ca_list(no_ca)
3540
3541
3542 def test_set_one_ca_list(self):
3543 """
3544 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003545 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003546 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003547 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003548 X509Name after the connection is set up.
3549 """
3550 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3551 cadesc = cacert.get_subject()
3552 def single_ca(ctx):
3553 ctx.set_client_ca_list([cadesc])
3554 return [cadesc]
3555 self._check_client_ca_list(single_ca)
3556
3557
3558 def test_set_multiple_ca_list(self):
3559 """
3560 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003561 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003562 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003563 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003564 X509Names after the connection is set up.
3565 """
3566 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3567 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3568
3569 sedesc = secert.get_subject()
3570 cldesc = clcert.get_subject()
3571
3572 def multiple_ca(ctx):
3573 L = [sedesc, cldesc]
3574 ctx.set_client_ca_list(L)
3575 return L
3576 self._check_client_ca_list(multiple_ca)
3577
3578
3579 def test_reset_ca_list(self):
3580 """
3581 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09003582 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003583 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003584 """
3585 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3586 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3587 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3588
3589 cadesc = cacert.get_subject()
3590 sedesc = secert.get_subject()
3591 cldesc = clcert.get_subject()
3592
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003593 def changed_ca(ctx):
3594 ctx.set_client_ca_list([sedesc, cldesc])
3595 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003596 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003597 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003598
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003599
3600 def test_mutated_ca_list(self):
3601 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003602 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003603 afterwards, this does not affect the list of CA names sent to the
3604 client.
3605 """
3606 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3607 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3608
3609 cadesc = cacert.get_subject()
3610 sedesc = secert.get_subject()
3611
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003612 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003613 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003614 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003615 L.append(sedesc)
3616 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003617 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003618
3619
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003620 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003621 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003622 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003623 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003624 """
3625 ctx = Context(TLSv1_METHOD)
3626 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003627 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003628 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003629 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003630
3631
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003632 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003633 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003634 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09003635 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003636 """
3637 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3638 cadesc = cacert.get_subject()
3639 def single_ca(ctx):
3640 ctx.add_client_ca(cacert)
3641 return [cadesc]
3642 self._check_client_ca_list(single_ca)
3643
3644
3645 def test_multiple_add_client_ca(self):
3646 """
3647 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09003648 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003649 """
3650 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3651 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3652
3653 cadesc = cacert.get_subject()
3654 sedesc = secert.get_subject()
3655
3656 def multiple_ca(ctx):
3657 ctx.add_client_ca(cacert)
3658 ctx.add_client_ca(secert)
3659 return [cadesc, sedesc]
3660 self._check_client_ca_list(multiple_ca)
3661
3662
3663 def test_set_and_add_client_ca(self):
3664 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003665 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
3666 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003667 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003668 """
3669 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3670 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3671 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3672
3673 cadesc = cacert.get_subject()
3674 sedesc = secert.get_subject()
3675 cldesc = clcert.get_subject()
3676
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003677 def mixed_set_add_ca(ctx):
3678 ctx.set_client_ca_list([cadesc, sedesc])
3679 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003680 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003681 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003682
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003683
3684 def test_set_after_add_client_ca(self):
3685 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003686 A call to :py:obj:`Context.set_client_ca_list` after a call to
3687 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003688 call with the names specified by the latter cal.
3689 """
3690 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3691 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3692 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3693
3694 cadesc = cacert.get_subject()
3695 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003696
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003697 def set_replaces_add_ca(ctx):
3698 ctx.add_client_ca(clcert)
3699 ctx.set_client_ca_list([cadesc])
3700 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003701 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003702 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003703
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003704
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003705
3706class ConnectionBIOTests(TestCase):
3707 """
3708 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3709 """
3710 def test_wantReadError(self):
3711 """
3712 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
3713 if there are no bytes available to be read from the BIO.
3714 """
3715 ctx = Context(TLSv1_METHOD)
3716 conn = Connection(ctx, None)
3717 self.assertRaises(WantReadError, conn.bio_read, 1024)
3718
3719
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003720 def test_buffer_size(self):
3721 """
3722 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3723 number of bytes to read and return.
3724 """
3725 ctx = Context(TLSv1_METHOD)
3726 conn = Connection(ctx, None)
3727 conn.set_connect_state()
3728 try:
3729 conn.do_handshake()
3730 except WantReadError:
3731 pass
3732 data = conn.bio_read(2)
3733 self.assertEqual(2, len(data))
3734
3735
3736 if not PY3:
3737 def test_buffer_size_long(self):
3738 """
3739 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3740 :py:obj:`long` as well as :py:obj:`int`.
3741 """
3742 ctx = Context(TLSv1_METHOD)
3743 conn = Connection(ctx, None)
3744 conn.set_connect_state()
3745 try:
3746 conn.do_handshake()
3747 except WantReadError:
3748 pass
3749 data = conn.bio_read(long(2))
3750 self.assertEqual(2, len(data))
3751
3752
3753
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003754
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003755class InfoConstantTests(TestCase):
3756 """
3757 Tests for assorted constants exposed for use in info callbacks.
3758 """
3759 def test_integers(self):
3760 """
3761 All of the info constants are integers.
3762
3763 This is a very weak test. It would be nice to have one that actually
3764 verifies that as certain info events happen, the value passed to the
3765 info callback matches up with the constant exposed by OpenSSL.SSL.
3766 """
3767 for const in [
3768 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3769 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3770 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3771 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3772 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
3773 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
3774
3775 self.assertTrue(isinstance(const, int))
3776
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003777
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003778if __name__ == '__main__':
3779 main()