blob: 2055b6daede1480b07bd1eb35a611b35d191f482 [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(
439 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
440 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(
450 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
451 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 """
548 filename = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
549 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 """
558 filename = self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
559 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 """
993 cafile = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
994 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(
1004 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
1005 )
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(
1044 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
1045 )
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(
1055 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
1056 )
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 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001202 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509` instance to add to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001203 the certificate chain.
1204
Jonathan Ballet648875f2011-07-16 14:14:58 +09001205 See :py:obj:`_create_certificate_chain` for the details of the certificate
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001206 chain tested.
1207
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.
1217 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001218 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001219 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001220 fObj.close()
1221
1222 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001223 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001224 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001225 fObj.close()
1226
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001227 # Create the server context
1228 serverContext = Context(TLSv1_METHOD)
1229 serverContext.use_privatekey(skey)
1230 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001231 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001232 serverContext.add_extra_chain_cert(icert)
1233
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001234 # Create the client
1235 clientContext = Context(TLSv1_METHOD)
1236 clientContext.set_verify(
1237 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001238 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001239
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001240 # Try it out.
1241 self._handshake_test(serverContext, clientContext)
1242
1243
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001244 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001245 """
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001246 Verify that :py:obj:`Context.use_certificate_chain_file` reads a
1247 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001248
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001249 The chain is tested by starting a server with scert and connecting to
1250 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001251 succeed.
1252 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001253 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001254 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1255
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001256 makedirs(certdir)
1257
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001258 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1259 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001260
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001261 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001262 with open(chainFile, 'wb') as fObj:
1263 # Most specific to least general.
1264 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1265 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1266 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1267
1268 with open(caFile, 'w') as fObj:
1269 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001270
1271 serverContext = Context(TLSv1_METHOD)
1272 serverContext.use_certificate_chain_file(chainFile)
1273 serverContext.use_privatekey(skey)
1274
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001275 clientContext = Context(TLSv1_METHOD)
1276 clientContext.set_verify(
1277 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001278 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001279
1280 self._handshake_test(serverContext, clientContext)
1281
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001282
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001283 def test_use_certificate_chain_file_bytes(self):
1284 """
1285 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1286 an instance of ``bytes``) to specify additional certificates to use to
1287 construct and verify a trust chain.
1288 """
1289 self._use_certificate_chain_file_test(
1290 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
1291 )
1292
1293
1294 def test_use_certificate_chain_file_unicode(self):
1295 """
1296 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1297 an instance of ``unicode``) to specify additional certificates to use
1298 to construct and verify a trust chain.
1299 """
1300 self._use_certificate_chain_file_test(
1301 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
1302 )
1303
1304
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001305 def test_use_certificate_chain_file_wrong_args(self):
1306 """
1307 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1308 if passed zero or more than one argument or when passed a non-byte
1309 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error` when
1310 passed a bad chain file name (for example, the name of a file which does
1311 not exist).
1312 """
1313 context = Context(TLSv1_METHOD)
1314 self.assertRaises(TypeError, context.use_certificate_chain_file)
1315 self.assertRaises(TypeError, context.use_certificate_chain_file, object())
1316 self.assertRaises(TypeError, context.use_certificate_chain_file, b"foo", object())
1317
1318 self.assertRaises(Error, context.use_certificate_chain_file, self.mktemp())
1319
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001320 # XXX load_client_ca
1321 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001322
1323 def test_get_verify_mode_wrong_args(self):
1324 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001325 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001326 arguments.
1327 """
1328 context = Context(TLSv1_METHOD)
1329 self.assertRaises(TypeError, context.get_verify_mode, None)
1330
1331
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001332 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001333 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001334 :py:obj:`Context.get_verify_mode` returns the verify mode flags previously
1335 passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001336 """
1337 context = Context(TLSv1_METHOD)
1338 self.assertEquals(context.get_verify_mode(), 0)
1339 context.set_verify(
1340 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1341 self.assertEquals(
1342 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1343
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001344
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001345 if not PY3:
1346 def test_set_verify_mode_long(self):
1347 """
1348 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1349 type :py:obj:`long` as well as :py:obj:`int`.
1350 """
1351 context = Context(TLSv1_METHOD)
1352 self.assertEquals(context.get_verify_mode(), 0)
1353 context.set_verify(
1354 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None)
1355 self.assertEquals(
1356 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1357
1358
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001359 def test_load_tmp_dh_wrong_args(self):
1360 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001361 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
1362 number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001363 """
1364 context = Context(TLSv1_METHOD)
1365 self.assertRaises(TypeError, context.load_tmp_dh)
1366 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1367 self.assertRaises(TypeError, context.load_tmp_dh, object())
1368
1369
1370 def test_load_tmp_dh_missing_file(self):
1371 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001372 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the specified file
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001373 does not exist.
1374 """
1375 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001376 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001377
1378
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001379 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001380 """
1381 Verify that calling ``Context.load_tmp_dh`` with the given filename
1382 does not raise an exception.
1383 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001384 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001385 with open(dhfilename, "w") as dhfile:
1386 dhfile.write(dhparam)
1387
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001388 context.load_tmp_dh(dhfilename)
1389 # XXX What should I assert here? -exarkun
1390
1391
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001392 def test_load_tmp_dh_bytes(self):
1393 """
1394 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1395 specified file (given as ``bytes``).
1396 """
1397 self._load_tmp_dh_test(
1398 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
1399 )
1400
1401
1402 def test_load_tmp_dh_unicode(self):
1403 """
1404 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1405 specified file (given as ``unicode``).
1406 """
1407 self._load_tmp_dh_test(
1408 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
1409 )
1410
1411
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001412 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001413 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001414 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001415 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001416 """
1417 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001418 for curve in get_elliptic_curves():
1419 # The only easily "assertable" thing is that it does not raise an
1420 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001421 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001422
1423
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001424 def test_set_cipher_list_bytes(self):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001425 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001426 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
1427 ciphers which connections created with the context object will be able
1428 to choose from.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001429 """
1430 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001431 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001432 conn = Connection(context, None)
1433 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001434
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001435
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001436 def test_set_cipher_list_text(self):
1437 """
1438 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
1439 the ciphers which connections created with the context object will be
1440 able to choose from.
1441 """
1442 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -05001443 context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001444 conn = Connection(context, None)
1445 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
1446
1447
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001448 def test_set_cipher_list_wrong_args(self):
1449 """
Jean-Paul Calderone17044832014-01-18 10:20:11 -05001450 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
1451 passed zero arguments or more than one argument or when passed a
1452 non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001453 passed an incorrect cipher list string.
1454 """
1455 context = Context(TLSv1_METHOD)
1456 self.assertRaises(TypeError, context.set_cipher_list)
1457 self.assertRaises(TypeError, context.set_cipher_list, object())
1458 self.assertRaises(TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object())
1459
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001460 self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001461
1462
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001463 def test_set_session_cache_mode_wrong_args(self):
1464 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001465 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1466 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001467 """
1468 context = Context(TLSv1_METHOD)
1469 self.assertRaises(TypeError, context.set_session_cache_mode)
1470 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1471
1472
1473 def test_get_session_cache_mode_wrong_args(self):
1474 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001475 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1476 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001477 """
1478 context = Context(TLSv1_METHOD)
1479 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1480
1481
1482 def test_session_cache_mode(self):
1483 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001484 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1485 cached. The setting can be retrieved via
1486 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001487 """
1488 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001489 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001490 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1491 self.assertEqual(SESS_CACHE_OFF, off)
1492 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1493
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001494 if not PY3:
1495 def test_session_cache_mode_long(self):
1496 """
1497 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1498 of type :py:obj:`long` as well as :py:obj:`int`.
1499 """
1500 context = Context(TLSv1_METHOD)
1501 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1502 self.assertEqual(
1503 SESS_CACHE_BOTH, context.get_session_cache_mode())
1504
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001505
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001506 def test_get_cert_store(self):
1507 """
1508 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store` instance.
1509 """
1510 context = Context(TLSv1_METHOD)
1511 store = context.get_cert_store()
1512 self.assertIsInstance(store, X509Store)
1513
1514
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001515
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001516class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1517 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001518 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
1519 :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001520 """
1521 def test_wrong_args(self):
1522 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001523 :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001524 with other than one argument.
1525 """
1526 context = Context(TLSv1_METHOD)
1527 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1528 self.assertRaises(
1529 TypeError, context.set_tlsext_servername_callback, 1, 2)
1530
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001531
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001532 def test_old_callback_forgotten(self):
1533 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001534 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001535 callback, the one it replaces is dereferenced.
1536 """
1537 def callback(connection):
1538 pass
1539
1540 def replacement(connection):
1541 pass
1542
1543 context = Context(TLSv1_METHOD)
1544 context.set_tlsext_servername_callback(callback)
1545
1546 tracker = ref(callback)
1547 del callback
1548
1549 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001550
1551 # One run of the garbage collector happens to work on CPython. PyPy
1552 # doesn't collect the underlying object until a second run for whatever
1553 # reason. That's fine, it still demonstrates our code has properly
1554 # dropped the reference.
1555 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001556 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001557
1558 callback = tracker()
1559 if callback is not None:
1560 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001561 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001562 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001563
1564
1565 def test_no_servername(self):
1566 """
1567 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001568 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
1569 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001570 """
1571 args = []
1572 def servername(conn):
1573 args.append((conn, conn.get_servername()))
1574 context = Context(TLSv1_METHOD)
1575 context.set_tlsext_servername_callback(servername)
1576
1577 # Lose our reference to it. The Context is responsible for keeping it
1578 # alive now.
1579 del servername
1580 collect()
1581
1582 # Necessary to actually accept the connection
1583 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1584 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1585
1586 # Do a little connection to trigger the logic
1587 server = Connection(context, None)
1588 server.set_accept_state()
1589
1590 client = Connection(Context(TLSv1_METHOD), None)
1591 client.set_connect_state()
1592
1593 self._interactInMemory(server, client)
1594
1595 self.assertEqual([(server, None)], args)
1596
1597
1598 def test_servername(self):
1599 """
1600 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +09001601 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
1602 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001603 """
1604 args = []
1605 def servername(conn):
1606 args.append((conn, conn.get_servername()))
1607 context = Context(TLSv1_METHOD)
1608 context.set_tlsext_servername_callback(servername)
1609
1610 # Necessary to actually accept the connection
1611 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1612 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1613
1614 # Do a little connection to trigger the logic
1615 server = Connection(context, None)
1616 server.set_accept_state()
1617
1618 client = Connection(Context(TLSv1_METHOD), None)
1619 client.set_connect_state()
1620 client.set_tlsext_host_name(b("foo1.example.com"))
1621
1622 self._interactInMemory(server, client)
1623
1624 self.assertEqual([(server, b("foo1.example.com"))], args)
1625
1626
Cory Benfield84a121e2014-03-31 20:30:25 +01001627class NextProtoNegotiationTests(TestCase, _LoopbackMixin):
1628 """
1629 Test for Next Protocol Negotiation in PyOpenSSL.
1630 """
Cory Benfieldba1820d2015-04-13 17:39:12 -04001631 if _lib.Cryptography_HAS_NEXTPROTONEG:
1632 def test_npn_success(self):
1633 """
1634 Tests that clients and servers that agree on the negotiated next
1635 protocol can correct establish a connection, and that the agreed
1636 protocol is reported by the connections.
1637 """
1638 advertise_args = []
1639 select_args = []
1640 def advertise(conn):
1641 advertise_args.append((conn,))
1642 return [b'http/1.1', b'spdy/2']
1643 def select(conn, options):
1644 select_args.append((conn, options))
1645 return b'spdy/2'
Cory Benfield84a121e2014-03-31 20:30:25 +01001646
Cory Benfieldba1820d2015-04-13 17:39:12 -04001647 server_context = Context(TLSv1_METHOD)
1648 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001649
Cory Benfieldba1820d2015-04-13 17:39:12 -04001650 client_context = Context(TLSv1_METHOD)
1651 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001652
Cory Benfieldba1820d2015-04-13 17:39:12 -04001653 # Necessary to actually accept the connection
1654 server_context.use_privatekey(
1655 load_privatekey(FILETYPE_PEM, server_key_pem))
1656 server_context.use_certificate(
1657 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001658
Cory Benfieldba1820d2015-04-13 17:39:12 -04001659 # Do a little connection to trigger the logic
1660 server = Connection(server_context, None)
1661 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001662
Cory Benfieldba1820d2015-04-13 17:39:12 -04001663 client = Connection(client_context, None)
1664 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001665
Cory Benfieldba1820d2015-04-13 17:39:12 -04001666 self._interactInMemory(server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001667
Cory Benfieldba1820d2015-04-13 17:39:12 -04001668 self.assertEqual([(server,)], advertise_args)
1669 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001670
Cory Benfieldba1820d2015-04-13 17:39:12 -04001671 self.assertEqual(server.get_next_proto_negotiated(), b'spdy/2')
1672 self.assertEqual(client.get_next_proto_negotiated(), b'spdy/2')
Cory Benfield84a121e2014-03-31 20:30:25 +01001673
1674
Cory Benfieldba1820d2015-04-13 17:39:12 -04001675 def test_npn_client_fail(self):
1676 """
1677 Tests that when clients and servers cannot agree on what protocol
1678 to use next that the TLS connection does not get established.
1679 """
1680 advertise_args = []
1681 select_args = []
1682 def advertise(conn):
1683 advertise_args.append((conn,))
1684 return [b'http/1.1', b'spdy/2']
1685 def select(conn, options):
1686 select_args.append((conn, options))
1687 return b''
Cory Benfield84a121e2014-03-31 20:30:25 +01001688
Cory Benfieldba1820d2015-04-13 17:39:12 -04001689 server_context = Context(TLSv1_METHOD)
1690 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001691
Cory Benfieldba1820d2015-04-13 17:39:12 -04001692 client_context = Context(TLSv1_METHOD)
1693 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001694
Cory Benfieldba1820d2015-04-13 17:39:12 -04001695 # Necessary to actually accept the connection
1696 server_context.use_privatekey(
1697 load_privatekey(FILETYPE_PEM, server_key_pem))
1698 server_context.use_certificate(
1699 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001700
Cory Benfieldba1820d2015-04-13 17:39:12 -04001701 # Do a little connection to trigger the logic
1702 server = Connection(server_context, None)
1703 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001704
Cory Benfieldba1820d2015-04-13 17:39:12 -04001705 client = Connection(client_context, None)
1706 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001707
Cory Benfieldba1820d2015-04-13 17:39:12 -04001708 # If the client doesn't return anything, the connection will fail.
1709 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001710
Cory Benfieldba1820d2015-04-13 17:39:12 -04001711 self.assertEqual([(server,)], advertise_args)
1712 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001713
1714
Cory Benfieldba1820d2015-04-13 17:39:12 -04001715 def test_npn_select_error(self):
1716 """
1717 Test that we can handle exceptions in the select callback. If
1718 select fails it should be fatal to the connection.
1719 """
1720 advertise_args = []
1721 def advertise(conn):
1722 advertise_args.append((conn,))
1723 return [b'http/1.1', b'spdy/2']
1724 def select(conn, options):
1725 raise TypeError
Cory Benfield0ea76e72015-03-22 09:05:28 +00001726
Cory Benfieldba1820d2015-04-13 17:39:12 -04001727 server_context = Context(TLSv1_METHOD)
1728 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001729
Cory Benfieldba1820d2015-04-13 17:39:12 -04001730 client_context = Context(TLSv1_METHOD)
1731 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001732
Cory Benfieldba1820d2015-04-13 17:39:12 -04001733 # Necessary to actually accept the connection
1734 server_context.use_privatekey(
1735 load_privatekey(FILETYPE_PEM, server_key_pem))
1736 server_context.use_certificate(
1737 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001738
Cory Benfieldba1820d2015-04-13 17:39:12 -04001739 # Do a little connection to trigger the logic
1740 server = Connection(server_context, None)
1741 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001742
Cory Benfieldba1820d2015-04-13 17:39:12 -04001743 client = Connection(client_context, None)
1744 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001745
Cory Benfieldba1820d2015-04-13 17:39:12 -04001746 # If the callback throws an exception it should be raised here.
1747 self.assertRaises(
1748 TypeError, self._interactInMemory, server, client
1749 )
1750 self.assertEqual([(server,)], advertise_args)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001751
1752
Cory Benfieldba1820d2015-04-13 17:39:12 -04001753 def test_npn_advertise_error(self):
1754 """
1755 Test that we can handle exceptions in the advertise callback. If
1756 advertise fails no NPN is advertised to the client.
1757 """
1758 select_args = []
1759 def advertise(conn):
1760 raise TypeError
1761 def select(conn, options):
1762 select_args.append((conn, options))
1763 return b''
Cory Benfield0ea76e72015-03-22 09:05:28 +00001764
Cory Benfieldba1820d2015-04-13 17:39:12 -04001765 server_context = Context(TLSv1_METHOD)
1766 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001767
Cory Benfieldba1820d2015-04-13 17:39:12 -04001768 client_context = Context(TLSv1_METHOD)
1769 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001770
Cory Benfieldba1820d2015-04-13 17:39:12 -04001771 # Necessary to actually accept the connection
1772 server_context.use_privatekey(
1773 load_privatekey(FILETYPE_PEM, server_key_pem))
1774 server_context.use_certificate(
1775 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001776
Cory Benfieldba1820d2015-04-13 17:39:12 -04001777 # Do a little connection to trigger the logic
1778 server = Connection(server_context, None)
1779 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001780
Cory Benfieldba1820d2015-04-13 17:39:12 -04001781 client = Connection(client_context, None)
1782 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001783
Cory Benfieldba1820d2015-04-13 17:39:12 -04001784 # If the client doesn't return anything, the connection will fail.
1785 self.assertRaises(
1786 TypeError, self._interactInMemory, server, client
1787 )
1788 self.assertEqual([], select_args)
1789
1790 else:
1791 # No NPN.
1792 def test_npn_not_implemented(self):
1793 # Test the context methods first.
1794 context = Context(TLSv1_METHOD)
1795 fail_methods = [
1796 context.set_npn_advertise_callback,
1797 context.set_npn_select_callback,
1798 ]
1799 for method in fail_methods:
1800 self.assertRaises(
1801 NotImplementedError, method, None
1802 )
1803
1804 # Now test a connection.
1805 conn = Connection(context)
1806 fail_methods = [
1807 conn.get_next_proto_negotiated,
1808 ]
1809 for method in fail_methods:
1810 self.assertRaises(NotImplementedError, method)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001811
1812
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001813
Cory Benfield12eae892014-06-07 15:42:56 +01001814class ApplicationLayerProtoNegotiationTests(TestCase, _LoopbackMixin):
1815 """
1816 Tests for ALPN in PyOpenSSL.
1817 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001818 # Skip tests on versions that don't support ALPN.
1819 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001820
Cory Benfielde46fa842015-04-13 16:50:49 -04001821 def test_alpn_success(self):
1822 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001823 Clients and servers that agree on the negotiated ALPN protocol can
1824 correct establish a connection, and the agreed protocol is reported
1825 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001826 """
1827 select_args = []
1828 def select(conn, options):
1829 select_args.append((conn, options))
1830 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001831
Cory Benfielde46fa842015-04-13 16:50:49 -04001832 client_context = Context(TLSv1_METHOD)
1833 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001834
Cory Benfielde46fa842015-04-13 16:50:49 -04001835 server_context = Context(TLSv1_METHOD)
1836 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001837
Cory Benfielde46fa842015-04-13 16:50:49 -04001838 # Necessary to actually accept the connection
1839 server_context.use_privatekey(
1840 load_privatekey(FILETYPE_PEM, server_key_pem))
1841 server_context.use_certificate(
1842 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001843
Cory Benfielde46fa842015-04-13 16:50:49 -04001844 # Do a little connection to trigger the logic
1845 server = Connection(server_context, None)
1846 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001847
Cory Benfielde46fa842015-04-13 16:50:49 -04001848 client = Connection(client_context, None)
1849 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001850
Cory Benfielde46fa842015-04-13 16:50:49 -04001851 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001852
Cory Benfielde46fa842015-04-13 16:50:49 -04001853 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
1854
1855 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1856 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001857
1858
Cory Benfielde46fa842015-04-13 16:50:49 -04001859 def test_alpn_set_on_connection(self):
1860 """
1861 The same as test_alpn_success, but setting the ALPN protocols on
1862 the connection rather than the context.
1863 """
1864 select_args = []
1865 def select(conn, options):
1866 select_args.append((conn, options))
1867 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001868
Cory Benfielde46fa842015-04-13 16:50:49 -04001869 # Setup the client context but don't set any ALPN protocols.
1870 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001871
Cory Benfielde46fa842015-04-13 16:50:49 -04001872 server_context = Context(TLSv1_METHOD)
1873 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001874
Cory Benfielde46fa842015-04-13 16:50:49 -04001875 # Necessary to actually accept the connection
1876 server_context.use_privatekey(
1877 load_privatekey(FILETYPE_PEM, server_key_pem))
1878 server_context.use_certificate(
1879 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001880
Cory Benfielde46fa842015-04-13 16:50:49 -04001881 # Do a little connection to trigger the logic
1882 server = Connection(server_context, None)
1883 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001884
Cory Benfielde46fa842015-04-13 16:50:49 -04001885 # Set the ALPN protocols on the client connection.
1886 client = Connection(client_context, None)
1887 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1888 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001889
Cory Benfielde46fa842015-04-13 16:50:49 -04001890 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001891
Cory Benfielde46fa842015-04-13 16:50:49 -04001892 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001893
Cory Benfielde46fa842015-04-13 16:50:49 -04001894 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1895 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001896
1897
Cory Benfielde46fa842015-04-13 16:50:49 -04001898 def test_alpn_server_fail(self):
1899 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001900 When clients and servers cannot agree on what protocol to use next
1901 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001902 """
1903 select_args = []
1904 def select(conn, options):
1905 select_args.append((conn, options))
1906 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001907
Cory Benfielde46fa842015-04-13 16:50:49 -04001908 client_context = Context(TLSv1_METHOD)
1909 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001910
Cory Benfielde46fa842015-04-13 16:50:49 -04001911 server_context = Context(TLSv1_METHOD)
1912 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001913
Cory Benfielde46fa842015-04-13 16:50:49 -04001914 # Necessary to actually accept the connection
1915 server_context.use_privatekey(
1916 load_privatekey(FILETYPE_PEM, server_key_pem))
1917 server_context.use_certificate(
1918 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001919
Cory Benfielde46fa842015-04-13 16:50:49 -04001920 # Do a little connection to trigger the logic
1921 server = Connection(server_context, None)
1922 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001923
Cory Benfielde46fa842015-04-13 16:50:49 -04001924 client = Connection(client_context, None)
1925 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001926
Cory Benfielde46fa842015-04-13 16:50:49 -04001927 # If the client doesn't return anything, the connection will fail.
1928 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001929
Cory Benfielde46fa842015-04-13 16:50:49 -04001930 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001931
1932
Cory Benfielde46fa842015-04-13 16:50:49 -04001933 def test_alpn_no_server(self):
1934 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001935 When clients and servers cannot agree on what protocol to use next
1936 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04001937 """
1938 client_context = Context(TLSv1_METHOD)
1939 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04001940
Cory Benfielde46fa842015-04-13 16:50:49 -04001941 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04001942
Cory Benfielde46fa842015-04-13 16:50:49 -04001943 # Necessary to actually accept the connection
1944 server_context.use_privatekey(
1945 load_privatekey(FILETYPE_PEM, server_key_pem))
1946 server_context.use_certificate(
1947 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04001948
Cory Benfielde46fa842015-04-13 16:50:49 -04001949 # Do a little connection to trigger the logic
1950 server = Connection(server_context, None)
1951 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001952
Cory Benfielde46fa842015-04-13 16:50:49 -04001953 client = Connection(client_context, None)
1954 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001955
Cory Benfielde46fa842015-04-13 16:50:49 -04001956 # Do the dance.
1957 self._interactInMemory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04001958
Cory Benfielde46fa842015-04-13 16:50:49 -04001959 self.assertEqual(client.get_alpn_proto_negotiated(), b'')
Cory Benfielde3d57152015-04-11 17:57:35 -04001960
1961
Cory Benfielde46fa842015-04-13 16:50:49 -04001962 def test_alpn_callback_exception(self):
1963 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001964 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04001965 """
1966 select_args = []
1967 def select(conn, options):
1968 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04001969 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001970
Cory Benfielde46fa842015-04-13 16:50:49 -04001971 client_context = Context(TLSv1_METHOD)
1972 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04001973
Cory Benfielde46fa842015-04-13 16:50:49 -04001974 server_context = Context(TLSv1_METHOD)
1975 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04001976
Cory Benfielde46fa842015-04-13 16:50:49 -04001977 # Necessary to actually accept the connection
1978 server_context.use_privatekey(
1979 load_privatekey(FILETYPE_PEM, server_key_pem))
1980 server_context.use_certificate(
1981 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04001982
Cory Benfielde46fa842015-04-13 16:50:49 -04001983 # Do a little connection to trigger the logic
1984 server = Connection(server_context, None)
1985 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001986
Cory Benfielde46fa842015-04-13 16:50:49 -04001987 client = Connection(client_context, None)
1988 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001989
Cory Benfielde46fa842015-04-13 16:50:49 -04001990 self.assertRaises(
1991 TypeError, self._interactInMemory, server, client
1992 )
1993 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfieldf1177e72015-04-12 09:11:49 -04001994
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001995 else:
1996 # No ALPN.
1997 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04001998 """
1999 If ALPN is not in OpenSSL, we should raise NotImplementedError.
2000 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002001 # Test the context methods first.
2002 context = Context(TLSv1_METHOD)
Cory Benfield307e9e62015-04-13 18:21:12 -04002003 self.assertRaises(
2004 NotImplementedError, context.set_alpn_protos, None
2005 )
2006 self.assertRaises(
2007 NotImplementedError, context.set_alpn_select_callback, None
2008 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002009
2010 # Now test a connection.
2011 conn = Connection(context)
Cory Benfield307e9e62015-04-13 18:21:12 -04002012 self.assertRaises(
2013 NotImplementedError, context.set_alpn_protos, None
2014 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002015
Cory Benfieldf1177e72015-04-12 09:11:49 -04002016
Cory Benfield12eae892014-06-07 15:42:56 +01002017
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002018class SessionTests(TestCase):
2019 """
2020 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
2021 """
2022 def test_construction(self):
2023 """
2024 :py:class:`Session` can be constructed with no arguments, creating a new
2025 instance of that type.
2026 """
2027 new_session = Session()
2028 self.assertTrue(isinstance(new_session, Session))
2029
2030
2031 def test_construction_wrong_args(self):
2032 """
2033 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
2034 is raised.
2035 """
2036 self.assertRaises(TypeError, Session, 123)
2037 self.assertRaises(TypeError, Session, "hello")
2038 self.assertRaises(TypeError, Session, object())
2039
2040
2041
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002042class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05002043 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002044 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002045 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002046 # XXX get_peer_certificate -> None
2047 # XXX sock_shutdown
2048 # XXX master_key -> TypeError
2049 # XXX server_random -> TypeError
2050 # XXX state_string
2051 # XXX connect -> TypeError
2052 # XXX connect_ex -> TypeError
2053 # XXX set_connect_state -> TypeError
2054 # XXX set_accept_state -> TypeError
2055 # XXX renegotiate_pending
2056 # XXX do_handshake -> TypeError
2057 # XXX bio_read -> TypeError
2058 # XXX recv -> TypeError
2059 # XXX send -> TypeError
2060 # XXX bio_write -> TypeError
2061
Rick Deane15b1472009-07-09 15:53:42 -05002062 def test_type(self):
2063 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002064 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002065 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002066 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002067 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05002068 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002069 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002070
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002071
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002072 def test_get_context(self):
2073 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002074 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
2075 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002076 """
2077 context = Context(TLSv1_METHOD)
2078 connection = Connection(context, None)
2079 self.assertIdentical(connection.get_context(), context)
2080
2081
2082 def test_get_context_wrong_args(self):
2083 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002084 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002085 arguments.
2086 """
2087 connection = Connection(Context(TLSv1_METHOD), None)
2088 self.assertRaises(TypeError, connection.get_context, None)
2089
2090
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002091 def test_set_context_wrong_args(self):
2092 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002093 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
2094 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002095 than 1.
2096 """
2097 ctx = Context(TLSv1_METHOD)
2098 connection = Connection(ctx, None)
2099 self.assertRaises(TypeError, connection.set_context)
2100 self.assertRaises(TypeError, connection.set_context, object())
2101 self.assertRaises(TypeError, connection.set_context, "hello")
2102 self.assertRaises(TypeError, connection.set_context, 1)
2103 self.assertRaises(TypeError, connection.set_context, 1, 2)
2104 self.assertRaises(
2105 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
2106 self.assertIdentical(ctx, connection.get_context())
2107
2108
2109 def test_set_context(self):
2110 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002111 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002112 for the connection.
2113 """
2114 original = Context(SSLv23_METHOD)
2115 replacement = Context(TLSv1_METHOD)
2116 connection = Connection(original, None)
2117 connection.set_context(replacement)
2118 self.assertIdentical(replacement, connection.get_context())
2119 # Lose our references to the contexts, just in case the Connection isn't
2120 # properly managing its own contributions to their reference counts.
2121 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002122 collect()
2123
2124
2125 def test_set_tlsext_host_name_wrong_args(self):
2126 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002127 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002128 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09002129 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002130 """
2131 conn = Connection(Context(TLSv1_METHOD), None)
2132 self.assertRaises(TypeError, conn.set_tlsext_host_name)
2133 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
2134 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
2135 self.assertRaises(
2136 TypeError, conn.set_tlsext_host_name, b("with\0null"))
2137
Abraham Martinc5484ba2015-03-25 15:33:05 +00002138 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002139 # On Python 3.x, don't accidentally implicitly convert from text.
2140 self.assertRaises(
2141 TypeError,
2142 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002143
2144
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002145 def test_get_servername_wrong_args(self):
2146 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002147 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002148 arguments.
2149 """
2150 connection = Connection(Context(TLSv1_METHOD), None)
2151 self.assertRaises(TypeError, connection.get_servername, object())
2152 self.assertRaises(TypeError, connection.get_servername, 1)
2153 self.assertRaises(TypeError, connection.get_servername, "hello")
2154
2155
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002156 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002157 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002158 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002159 immediate read.
2160 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002161 connection = Connection(Context(TLSv1_METHOD), None)
2162 self.assertEquals(connection.pending(), 0)
2163
2164
2165 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002166 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002167 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002168 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002169 connection = Connection(Context(TLSv1_METHOD), None)
2170 self.assertRaises(TypeError, connection.pending, None)
2171
2172
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002173 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002174 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002175 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002176 argument or with the wrong number of arguments.
2177 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002178 connection = Connection(Context(TLSv1_METHOD), socket())
2179 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002180 self.assertRaises(TypeError, connection.connect)
2181 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002182
2183
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002184 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002185 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002186 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002187 connect method raises it.
2188 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002189 client = socket()
2190 context = Context(TLSv1_METHOD)
2191 clientSSL = Connection(context, client)
2192 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04002193 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002194
2195
2196 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002197 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002198 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002199 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002200 port = socket()
2201 port.bind(('', 0))
2202 port.listen(3)
2203
2204 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002205 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2206 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002207
2208
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002209 if platform == "darwin":
2210 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2211 else:
2212 def test_connect_ex(self):
2213 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002214 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002215 errno instead of raising an exception.
2216 """
2217 port = socket()
2218 port.bind(('', 0))
2219 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002220
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002221 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2222 clientSSL.setblocking(False)
2223 result = clientSSL.connect_ex(port.getsockname())
2224 expected = (EINPROGRESS, EWOULDBLOCK)
2225 self.assertTrue(
2226 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002227
2228
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002229 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002230 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002231 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002232 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002233 connection = Connection(Context(TLSv1_METHOD), socket())
2234 self.assertRaises(TypeError, connection.accept, None)
2235
2236
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002237 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002238 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002239 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
2240 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002241 connection originated from.
2242 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002243 ctx = Context(TLSv1_METHOD)
2244 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2245 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002246 port = socket()
2247 portSSL = Connection(ctx, port)
2248 portSSL.bind(('', 0))
2249 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002250
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002251 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002252
2253 # Calling portSSL.getsockname() here to get the server IP address sounds
2254 # great, but frequently fails on Windows.
2255 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002256
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002257 serverSSL, address = portSSL.accept()
2258
2259 self.assertTrue(isinstance(serverSSL, Connection))
2260 self.assertIdentical(serverSSL.get_context(), ctx)
2261 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002262
2263
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002264 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002265 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002266 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002267 number of arguments or with arguments other than integers.
2268 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002269 connection = Connection(Context(TLSv1_METHOD), None)
2270 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04002271 self.assertRaises(TypeError, connection.get_shutdown, None)
2272 self.assertRaises(TypeError, connection.set_shutdown)
2273 self.assertRaises(TypeError, connection.set_shutdown, None)
2274 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002275
2276
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002277 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002278 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002279 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002280 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002281 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002282 self.assertFalse(server.shutdown())
2283 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002284 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002285 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
2286 client.shutdown()
2287 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
2288 self.assertRaises(ZeroReturnError, server.recv, 1024)
2289 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002290
2291
Paul Aurichc85e0862015-01-08 08:34:33 -08002292 def test_shutdown_closed(self):
2293 """
2294 If the underlying socket is closed, :py:obj:`Connection.shutdown` propagates the
2295 write error from the low level write call.
2296 """
2297 server, client = self._loopback()
2298 server.sock_shutdown(2)
2299 exc = self.assertRaises(SysCallError, server.shutdown)
2300 if platform == "win32":
2301 self.assertEqual(exc.args[0], ESHUTDOWN)
2302 else:
2303 self.assertEqual(exc.args[0], EPIPE)
2304
2305
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002306 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002307 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002308 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002309 process.
2310 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002311 connection = Connection(Context(TLSv1_METHOD), socket())
2312 connection.set_shutdown(RECEIVED_SHUTDOWN)
2313 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2314
2315
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002316 if not PY3:
2317 def test_set_shutdown_long(self):
2318 """
2319 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
2320 of type :py:obj:`long` as well as :py:obj:`int`.
2321 """
2322 connection = Connection(Context(TLSv1_METHOD), socket())
2323 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
2324 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2325
2326
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002327 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002328 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002329 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
2330 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002331 with any arguments.
2332 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002333 conn = Connection(Context(TLSv1_METHOD), None)
2334 self.assertRaises(TypeError, conn.get_app_data, None)
2335 self.assertRaises(TypeError, conn.set_app_data)
2336 self.assertRaises(TypeError, conn.set_app_data, None, None)
2337
2338
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002339 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002340 """
2341 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002342 :py:obj:`Connection.set_app_data` and later retrieved with
2343 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002344 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002345 conn = Connection(Context(TLSv1_METHOD), None)
2346 app_data = object()
2347 conn.set_app_data(app_data)
2348 self.assertIdentical(conn.get_app_data(), app_data)
2349
2350
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002351 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002352 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002353 :py:obj:`Connection.makefile` is not implemented and calling that method raises
2354 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002355 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002356 conn = Connection(Context(TLSv1_METHOD), None)
2357 self.assertRaises(NotImplementedError, conn.makefile)
2358
2359
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002360 def test_get_peer_cert_chain_wrong_args(self):
2361 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002362 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002363 arguments.
2364 """
2365 conn = Connection(Context(TLSv1_METHOD), None)
2366 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
2367 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
2368 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
2369 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
2370
2371
2372 def test_get_peer_cert_chain(self):
2373 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002374 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002375 the connected server returned for the certification verification.
2376 """
2377 chain = _create_certificate_chain()
2378 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2379
2380 serverContext = Context(TLSv1_METHOD)
2381 serverContext.use_privatekey(skey)
2382 serverContext.use_certificate(scert)
2383 serverContext.add_extra_chain_cert(icert)
2384 serverContext.add_extra_chain_cert(cacert)
2385 server = Connection(serverContext, None)
2386 server.set_accept_state()
2387
2388 # Create the client
2389 clientContext = Context(TLSv1_METHOD)
2390 clientContext.set_verify(VERIFY_NONE, verify_cb)
2391 client = Connection(clientContext, None)
2392 client.set_connect_state()
2393
2394 self._interactInMemory(client, server)
2395
2396 chain = client.get_peer_cert_chain()
2397 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002398 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002399 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002400 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002401 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002402 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002403 "Authority Certificate", chain[2].get_subject().CN)
2404
2405
2406 def test_get_peer_cert_chain_none(self):
2407 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002408 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002409 certificate chain.
2410 """
2411 ctx = Context(TLSv1_METHOD)
2412 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2413 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2414 server = Connection(ctx, None)
2415 server.set_accept_state()
2416 client = Connection(Context(TLSv1_METHOD), None)
2417 client.set_connect_state()
2418 self._interactInMemory(client, server)
2419 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002420
2421
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002422 def test_get_session_wrong_args(self):
2423 """
2424 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
2425 with any arguments.
2426 """
2427 ctx = Context(TLSv1_METHOD)
2428 server = Connection(ctx, None)
2429 self.assertRaises(TypeError, server.get_session, 123)
2430 self.assertRaises(TypeError, server.get_session, "hello")
2431 self.assertRaises(TypeError, server.get_session, object())
2432
2433
2434 def test_get_session_unconnected(self):
2435 """
2436 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
2437 an object which has not been connected.
2438 """
2439 ctx = Context(TLSv1_METHOD)
2440 server = Connection(ctx, None)
2441 session = server.get_session()
2442 self.assertIdentical(None, session)
2443
2444
2445 def test_server_get_session(self):
2446 """
2447 On the server side of a connection, :py:obj:`Connection.get_session`
2448 returns a :py:class:`Session` instance representing the SSL session for
2449 that connection.
2450 """
2451 server, client = self._loopback()
2452 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002453 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002454
2455
2456 def test_client_get_session(self):
2457 """
2458 On the client side of a connection, :py:obj:`Connection.get_session`
2459 returns a :py:class:`Session` instance representing the SSL session for
2460 that connection.
2461 """
2462 server, client = self._loopback()
2463 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002464 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002465
2466
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002467 def test_set_session_wrong_args(self):
2468 """
2469 If called with an object that is not an instance of :py:class:`Session`,
2470 or with other than one argument, :py:obj:`Connection.set_session` raises
2471 :py:obj:`TypeError`.
2472 """
2473 ctx = Context(TLSv1_METHOD)
2474 connection = Connection(ctx, None)
2475 self.assertRaises(TypeError, connection.set_session)
2476 self.assertRaises(TypeError, connection.set_session, 123)
2477 self.assertRaises(TypeError, connection.set_session, "hello")
2478 self.assertRaises(TypeError, connection.set_session, object())
2479 self.assertRaises(
2480 TypeError, connection.set_session, Session(), Session())
2481
2482
2483 def test_client_set_session(self):
2484 """
2485 :py:obj:`Connection.set_session`, when used prior to a connection being
2486 established, accepts a :py:class:`Session` instance and causes an
2487 attempt to re-use the session it represents when the SSL handshake is
2488 performed.
2489 """
2490 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2491 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2492 ctx = Context(TLSv1_METHOD)
2493 ctx.use_privatekey(key)
2494 ctx.use_certificate(cert)
2495 ctx.set_session_id("unity-test")
2496
2497 def makeServer(socket):
2498 server = Connection(ctx, socket)
2499 server.set_accept_state()
2500 return server
2501
2502 originalServer, originalClient = self._loopback(
2503 serverFactory=makeServer)
2504 originalSession = originalClient.get_session()
2505
2506 def makeClient(socket):
2507 client = self._loopbackClientFactory(socket)
2508 client.set_session(originalSession)
2509 return client
2510 resumedServer, resumedClient = self._loopback(
2511 serverFactory=makeServer,
2512 clientFactory=makeClient)
2513
2514 # This is a proxy: in general, we have no access to any unique
2515 # identifier for the session (new enough versions of OpenSSL expose a
2516 # hash which could be usable, but "new enough" is very, very new).
2517 # Instead, exploit the fact that the master key is re-used if the
2518 # session is re-used. As long as the master key for the two connections
2519 # is the same, the session was re-used!
2520 self.assertEqual(
2521 originalServer.master_key(), resumedServer.master_key())
2522
2523
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002524 def test_set_session_wrong_method(self):
2525 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002526 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
2527 instance associated with a context using a different SSL method than the
2528 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
2529 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002530 """
2531 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2532 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2533 ctx = Context(TLSv1_METHOD)
2534 ctx.use_privatekey(key)
2535 ctx.use_certificate(cert)
2536 ctx.set_session_id("unity-test")
2537
2538 def makeServer(socket):
2539 server = Connection(ctx, socket)
2540 server.set_accept_state()
2541 return server
2542
2543 originalServer, originalClient = self._loopback(
2544 serverFactory=makeServer)
2545 originalSession = originalClient.get_session()
2546
2547 def makeClient(socket):
2548 # Intentionally use a different, incompatible method here.
2549 client = Connection(Context(SSLv3_METHOD), socket)
2550 client.set_connect_state()
2551 client.set_session(originalSession)
2552 return client
2553
2554 self.assertRaises(
2555 Error,
2556 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2557
2558
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002559 def test_wantWriteError(self):
2560 """
2561 :py:obj:`Connection` methods which generate output raise
2562 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2563 fail indicating a should-write state.
2564 """
2565 client_socket, server_socket = socket_pair()
2566 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002567 # anything. Only write a single byte at a time so we can be sure we
2568 # completely fill the buffer. Even though the socket API is allowed to
2569 # signal a short write via its return value it seems this doesn't
2570 # always happen on all platforms (FreeBSD and OS X particular) for the
2571 # very last bit of available buffer space.
2572 msg = b"x"
2573 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002574 try:
2575 client_socket.send(msg)
2576 except error as e:
2577 if e.errno == EWOULDBLOCK:
2578 break
2579 raise
2580 else:
2581 self.fail(
2582 "Failed to fill socket buffer, cannot test BIO want write")
2583
2584 ctx = Context(TLSv1_METHOD)
2585 conn = Connection(ctx, client_socket)
2586 # Client's speak first, so make it an SSL client
2587 conn.set_connect_state()
2588 self.assertRaises(WantWriteError, conn.do_handshake)
2589
2590 # XXX want_read
2591
Fedor Brunner416f4a12014-03-28 13:18:38 +01002592 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002593 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002594 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2595 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002596 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002597 ctx = Context(TLSv1_METHOD)
2598 connection = Connection(ctx, None)
2599 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002600
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002601
Fedor Brunner416f4a12014-03-28 13:18:38 +01002602 def test_get_peer_finished_before_connect(self):
2603 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002604 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2605 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002606 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002607 ctx = Context(TLSv1_METHOD)
2608 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002609 self.assertEqual(connection.get_peer_finished(), None)
2610
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002611
Fedor Brunner416f4a12014-03-28 13:18:38 +01002612 def test_get_finished(self):
2613 """
2614 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002615 message send from client, or server. Finished messages are send during
2616 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002617 """
2618
Fedor Brunner5747b932014-03-05 14:22:34 +01002619 server, client = self._loopback()
2620
2621 self.assertNotEqual(server.get_finished(), None)
2622 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002623
Jean-Paul Calderoned979f232014-03-30 11:58:00 -04002624
Fedor Brunner416f4a12014-03-28 13:18:38 +01002625 def test_get_peer_finished(self):
2626 """
2627 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002628 message received from client, or server. Finished messages are send
2629 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002630 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002631 server, client = self._loopback()
2632
2633 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002634 self.assertTrue(len(server.get_peer_finished()) > 0)
2635
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002636
Fedor Brunner416f4a12014-03-28 13:18:38 +01002637 def test_tls_finished_message_symmetry(self):
2638 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002639 The TLS Finished message send by server must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002640 received by client.
2641
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002642 The TLS Finished message send by client must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002643 received by server.
2644 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002645 server, client = self._loopback()
2646
Fedor Brunner5747b932014-03-05 14:22:34 +01002647 self.assertEqual(server.get_finished(), client.get_peer_finished())
2648 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002649
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002650
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002651 def test_get_cipher_name_before_connect(self):
2652 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002653 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2654 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002655 """
2656 ctx = Context(TLSv1_METHOD)
2657 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002658 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002659
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002660
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002661 def test_get_cipher_name(self):
2662 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002663 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2664 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002665 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002666 server, client = self._loopback()
2667 server_cipher_name, client_cipher_name = \
2668 server.get_cipher_name(), client.get_cipher_name()
2669
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002670 self.assertIsInstance(server_cipher_name, text_type)
2671 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002672
2673 self.assertEqual(server_cipher_name, client_cipher_name)
2674
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002675
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002676 def test_get_cipher_version_before_connect(self):
2677 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002678 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2679 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002680 """
2681 ctx = Context(TLSv1_METHOD)
2682 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002683 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002684
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002685
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002686 def test_get_cipher_version(self):
2687 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002688 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2689 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002690 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002691 server, client = self._loopback()
2692 server_cipher_version, client_cipher_version = \
2693 server.get_cipher_version(), client.get_cipher_version()
2694
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002695 self.assertIsInstance(server_cipher_version, text_type)
2696 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002697
2698 self.assertEqual(server_cipher_version, client_cipher_version)
2699
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002700
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002701 def test_get_cipher_bits_before_connect(self):
2702 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002703 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2704 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002705 """
2706 ctx = Context(TLSv1_METHOD)
2707 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002708 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002709
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002710
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002711 def test_get_cipher_bits(self):
2712 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002713 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2714 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002715 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002716 server, client = self._loopback()
2717 server_cipher_bits, client_cipher_bits = \
2718 server.get_cipher_bits(), client.get_cipher_bits()
2719
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002720 self.assertIsInstance(server_cipher_bits, int)
2721 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002722
2723 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002724
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002725
2726
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002727class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002728 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002729 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002730 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002731 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002732 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002733 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002734 arguments.
2735 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002736 connection = Connection(Context(TLSv1_METHOD), None)
2737 self.assertRaises(TypeError, connection.get_cipher_list, None)
2738
2739
2740 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002741 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002742 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2743 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002744 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002745 connection = Connection(Context(TLSv1_METHOD), None)
2746 ciphers = connection.get_cipher_list()
2747 self.assertTrue(isinstance(ciphers, list))
2748 for cipher in ciphers:
2749 self.assertTrue(isinstance(cipher, str))
2750
2751
2752
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002753class ConnectionSendTests(TestCase, _LoopbackMixin):
2754 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002755 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002756 """
2757 def test_wrong_args(self):
2758 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002759 When called with arguments other than string argument for its first
2760 parameter or more than two arguments, :py:obj:`Connection.send` raises
2761 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002762 """
2763 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002764 self.assertRaises(TypeError, connection.send)
2765 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002766 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002767
2768
2769 def test_short_bytes(self):
2770 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002771 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002772 and returns the number of bytes sent.
2773 """
2774 server, client = self._loopback()
2775 count = server.send(b('xy'))
2776 self.assertEquals(count, 2)
2777 self.assertEquals(client.recv(2), b('xy'))
2778
Abraham Martinef063482015-03-25 14:06:24 +00002779
2780 def test_text(self):
2781 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002782 When passed a text, :py:obj:`Connection.send` transmits all of it and
2783 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002784 """
2785 server, client = self._loopback()
2786 with catch_warnings(record=True) as w:
2787 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002788 count = server.send(b"xy".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002789 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002790 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002791 WARNING_TYPE_EXPECTED
2792 ),
2793 str(w[-1].message)
2794 )
2795 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinef063482015-03-25 14:06:24 +00002796 self.assertEquals(count, 2)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002797 self.assertEquals(client.recv(2), b"xy")
Abraham Martinef063482015-03-25 14:06:24 +00002798
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002799 try:
2800 memoryview
2801 except NameError:
2802 "cannot test sending memoryview without memoryview"
2803 else:
2804 def test_short_memoryview(self):
2805 """
2806 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002807 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002808 bytes sent.
2809 """
2810 server, client = self._loopback()
2811 count = server.send(memoryview(b('xy')))
2812 self.assertEquals(count, 2)
2813 self.assertEquals(client.recv(2), b('xy'))
2814
2815
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002816 try:
2817 buffer
2818 except NameError:
2819 "cannot test sending buffer without buffer"
2820 else:
2821 def test_short_buffer(self):
2822 """
2823 When passed a buffer containing a small number of bytes,
2824 :py:obj:`Connection.send` transmits all of them and returns the number of
2825 bytes sent.
2826 """
2827 server, client = self._loopback()
2828 count = server.send(buffer(b('xy')))
2829 self.assertEquals(count, 2)
2830 self.assertEquals(client.recv(2), b('xy'))
2831
2832
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002833
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002834def _make_memoryview(size):
2835 """
2836 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2837 size.
2838 """
2839 return memoryview(bytearray(size))
2840
2841
2842
Cory Benfield62d10332014-06-15 10:03:41 +01002843class ConnectionRecvIntoTests(TestCase, _LoopbackMixin):
2844 """
2845 Tests for :py:obj:`Connection.recv_into`
2846 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002847 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002848 """
2849 Assert that when the given buffer is passed to
2850 ``Connection.recv_into``, whatever bytes are available to be received
2851 that fit into that buffer are written into that buffer.
2852 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002853 output_buffer = factory(5)
2854
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002855 server, client = self._loopback()
2856 server.send(b('xy'))
2857
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002858 self.assertEqual(client.recv_into(output_buffer), 2)
2859 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002860
2861
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002862 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002863 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002864 :py:obj:`Connection.recv_into` can be passed a ``bytearray`` instance
2865 and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002866 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002867 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002868
2869
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002870 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002871 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002872 Assert that when the given buffer is passed to ``Connection.recv_into``
2873 along with a value for ``nbytes`` that is less than the size of that
2874 buffer, only ``nbytes`` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002875 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002876 output_buffer = factory(10)
2877
Cory Benfield62d10332014-06-15 10:03:41 +01002878 server, client = self._loopback()
2879 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002880
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002881 self.assertEqual(client.recv_into(output_buffer, 5), 5)
2882 self.assertEqual(
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002883 output_buffer, bytearray(b('abcde\x00\x00\x00\x00\x00'))
2884 )
2885
2886
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002887 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002888 """
2889 When called with a ``bytearray`` instance,
2890 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter and
2891 doesn't copy in more than that number of bytes.
2892 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002893 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002894
2895
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002896 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002897 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002898 Assert that if there are more bytes available to be read from the
2899 receive buffer than would fit into the buffer passed to
2900 :py:obj:`Connection.recv_into`, only as many as fit are written into
2901 it.
Cory Benfield62d10332014-06-15 10:03:41 +01002902 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002903 output_buffer = factory(5)
2904
Cory Benfield62d10332014-06-15 10:03:41 +01002905 server, client = self._loopback()
2906 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002907
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002908 self.assertEqual(client.recv_into(output_buffer), 5)
2909 self.assertEqual(output_buffer, bytearray(b('abcde')))
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002910 rest = client.recv(5)
2911 self.assertEqual(b('fghij'), rest)
2912
2913
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002914 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002915 """
2916 When called with a ``bytearray`` instance,
2917 :py:obj:`Connection.recv_into` respects the size of the array and
2918 doesn't write more bytes into it than will fit.
2919 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002920 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002921
2922
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002923 def _really_doesnt_overfill_test(self, factory):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002924 """
2925 Assert that if the value given by ``nbytes`` is greater than the actual
2926 size of the output buffer passed to :py:obj:`Connection.recv_into`, the
2927 behavior is as if no value was given for ``nbytes`` at all.
2928 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002929 output_buffer = factory(5)
2930
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002931 server, client = self._loopback()
2932 server.send(b('abcdefghij'))
2933
2934 self.assertEqual(client.recv_into(output_buffer, 50), 5)
2935 self.assertEqual(output_buffer, bytearray(b('abcde')))
2936 rest = client.recv(5)
2937 self.assertEqual(b('fghij'), rest)
2938
2939
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002940 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002941 """
2942 When called with a ``bytearray`` instance and an ``nbytes`` value that
2943 is too large, :py:obj:`Connection.recv_into` respects the size of the
2944 array and not the ``nbytes`` value and doesn't write more bytes into
2945 the buffer than will fit.
2946 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002947 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002948
2949
Cory Benfield62d10332014-06-15 10:03:41 +01002950 try:
2951 memoryview
2952 except NameError:
2953 "cannot test recv_into memoryview without memoryview"
2954 else:
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002955 def test_memoryview_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002956 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002957 :py:obj:`Connection.recv_into` can be passed a ``memoryview``
2958 instance and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002959 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002960 self._no_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002961
2962
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002963 def test_memoryview_respects_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002964 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002965 When called with a ``memoryview`` instance,
2966 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter
2967 and doesn't copy more than that number of bytes in.
Cory Benfield62d10332014-06-15 10:03:41 +01002968 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002969 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002970
2971
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002972 def test_memoryview_doesnt_overfill(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002973 """
Jean-Paul Calderone8fd82552015-03-15 17:21:07 -04002974 When called with a ``memoryview`` instance,
2975 :py:obj:`Connection.recv_into` respects the size of the array and
2976 doesn't write more bytes into it than will fit.
Cory Benfield62d10332014-06-15 10:03:41 +01002977 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002978 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002979
2980
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002981 def test_memoryview_really_doesnt_overfill(self):
2982 """
2983 When called with a ``memoryview`` instance and an ``nbytes`` value
2984 that is too large, :py:obj:`Connection.recv_into` respects the size
2985 of the array and not the ``nbytes`` value and doesn't write more
2986 bytes into the buffer than will fit.
2987 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002988 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002989
2990
Cory Benfield62d10332014-06-15 10:03:41 +01002991
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002992class ConnectionSendallTests(TestCase, _LoopbackMixin):
2993 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002994 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002995 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002996 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002997 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002998 When called with arguments other than a string argument for its first
2999 parameter or with more than two arguments, :py:obj:`Connection.sendall`
3000 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003001 """
3002 connection = Connection(Context(TLSv1_METHOD), None)
3003 self.assertRaises(TypeError, connection.sendall)
3004 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003005 self.assertRaises(
3006 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003007
3008
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003009 def test_short(self):
3010 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003011 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003012 it.
3013 """
3014 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04003015 server.sendall(b('x'))
3016 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003017
3018
Abraham Martinef063482015-03-25 14:06:24 +00003019 def test_text(self):
3020 """
Jean-Paul Calderone93477422015-04-13 20:38:57 -04003021 :py:obj:`Connection.sendall` transmits all the content in the string
3022 passed to it raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003023 """
3024 server, client = self._loopback()
3025 with catch_warnings(record=True) as w:
3026 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003027 server.sendall(b"x".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003028 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003029 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003030 WARNING_TYPE_EXPECTED
3031 ),
3032 str(w[-1].message)
3033 )
3034 self.assertIs(w[-1].category, DeprecationWarning)
3035 self.assertEquals(client.recv(1), b"x")
Abraham Martinef063482015-03-25 14:06:24 +00003036
3037
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003038 try:
3039 memoryview
3040 except NameError:
3041 "cannot test sending memoryview without memoryview"
3042 else:
3043 def test_short_memoryview(self):
3044 """
3045 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003046 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003047 """
3048 server, client = self._loopback()
3049 server.sendall(memoryview(b('x')))
3050 self.assertEquals(client.recv(1), b('x'))
3051
3052
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003053 try:
3054 buffer
3055 except NameError:
3056 "cannot test sending buffers without buffers"
3057 else:
3058 def test_short_buffers(self):
3059 """
3060 When passed a buffer containing a small number of bytes,
3061 :py:obj:`Connection.sendall` transmits all of them.
3062 """
3063 server, client = self._loopback()
3064 server.sendall(buffer(b('x')))
3065 self.assertEquals(client.recv(1), b('x'))
3066
3067
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003068 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003069 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003070 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003071 it even if this requires multiple calls of an underlying write function.
3072 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003073 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003074 # Should be enough, underlying SSL_write should only do 16k at a time.
3075 # On Windows, after 32k of bytes the write will block (forever - because
3076 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04003077 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003078 server.sendall(message)
3079 accum = []
3080 received = 0
3081 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003082 data = client.recv(1024)
3083 accum.append(data)
3084 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04003085 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003086
3087
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003088 def test_closed(self):
3089 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003090 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003091 write error from the low level write call.
3092 """
3093 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003094 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003095 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003096 if platform == "win32":
3097 self.assertEqual(exc.args[0], ESHUTDOWN)
3098 else:
3099 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003100
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003101
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04003102
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003103class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
3104 """
3105 Tests for SSL renegotiation APIs.
3106 """
3107 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003108 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003109 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003110 arguments.
3111 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003112 connection = Connection(Context(TLSv1_METHOD), None)
3113 self.assertRaises(TypeError, connection.renegotiate, None)
3114
3115
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003116 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003117 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003118 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003119 any arguments.
3120 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003121 connection = Connection(Context(TLSv1_METHOD), None)
3122 self.assertRaises(TypeError, connection.total_renegotiations, None)
3123
3124
3125 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003126 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003127 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003128 renegotiations have happened.
3129 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003130 connection = Connection(Context(TLSv1_METHOD), None)
3131 self.assertEquals(connection.total_renegotiations(), 0)
3132
3133
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003134# def test_renegotiate(self):
3135# """
3136# """
3137# server, client = self._loopback()
3138
3139# server.send("hello world")
3140# self.assertEquals(client.recv(len("hello world")), "hello world")
3141
3142# self.assertEquals(server.total_renegotiations(), 0)
3143# self.assertTrue(server.renegotiate())
3144
3145# server.setblocking(False)
3146# client.setblocking(False)
3147# while server.renegotiate_pending():
3148# client.do_handshake()
3149# server.do_handshake()
3150
3151# self.assertEquals(server.total_renegotiations(), 1)
3152
3153
3154
3155
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003156class ErrorTests(TestCase):
3157 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003158 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003159 """
3160 def test_type(self):
3161 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003162 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003163 """
3164 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05003165 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05003166
3167
3168
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003169class ConstantsTests(TestCase):
3170 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003171 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003172
3173 These are values defined by OpenSSL intended only to be used as flags to
3174 OpenSSL APIs. The only assertions it seems can be made about them is
3175 their values.
3176 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003177 # unittest.TestCase has no skip mechanism
3178 if OP_NO_QUERY_MTU is not None:
3179 def test_op_no_query_mtu(self):
3180 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003181 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003182 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003183 """
3184 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
3185 else:
3186 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003187
3188
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003189 if OP_COOKIE_EXCHANGE is not None:
3190 def test_op_cookie_exchange(self):
3191 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003192 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003193 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003194 """
3195 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
3196 else:
3197 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003198
3199
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003200 if OP_NO_TICKET is not None:
3201 def test_op_no_ticket(self):
3202 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003203 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003204 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003205 """
3206 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04003207 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003208 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05003209
3210
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003211 if OP_NO_COMPRESSION is not None:
3212 def test_op_no_compression(self):
3213 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003214 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
3215 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003216 """
3217 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
3218 else:
3219 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3220
3221
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003222 def test_sess_cache_off(self):
3223 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003224 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3225 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003226 """
3227 self.assertEqual(0x0, SESS_CACHE_OFF)
3228
3229
3230 def test_sess_cache_client(self):
3231 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003232 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3233 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003234 """
3235 self.assertEqual(0x1, SESS_CACHE_CLIENT)
3236
3237
3238 def test_sess_cache_server(self):
3239 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003240 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3241 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003242 """
3243 self.assertEqual(0x2, SESS_CACHE_SERVER)
3244
3245
3246 def test_sess_cache_both(self):
3247 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003248 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3249 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003250 """
3251 self.assertEqual(0x3, SESS_CACHE_BOTH)
3252
3253
3254 def test_sess_cache_no_auto_clear(self):
3255 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003256 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3257 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3258 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003259 """
3260 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
3261
3262
3263 def test_sess_cache_no_internal_lookup(self):
3264 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003265 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3266 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3267 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003268 """
3269 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
3270
3271
3272 def test_sess_cache_no_internal_store(self):
3273 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003274 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3275 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3276 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003277 """
3278 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
3279
3280
3281 def test_sess_cache_no_internal(self):
3282 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003283 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3284 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
3285 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003286 """
3287 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
3288
3289
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04003290
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003291class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05003292 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003293 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003294 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003295 def _server(self, sock):
3296 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003297 Create a new server-side SSL :py:obj:`Connection` object wrapped around
3298 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003299 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003300 # Create the server side Connection. This is mostly setup boilerplate
3301 # - use TLSv1, use a particular certificate, etc.
3302 server_ctx = Context(TLSv1_METHOD)
3303 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
3304 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
3305 server_store = server_ctx.get_cert_store()
3306 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3307 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3308 server_ctx.check_privatekey()
3309 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003310 # Here the Connection is actually created. If None is passed as the 2nd
3311 # parameter, it indicates a memory BIO should be created.
3312 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003313 server_conn.set_accept_state()
3314 return server_conn
3315
3316
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003317 def _client(self, sock):
3318 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003319 Create a new client-side SSL :py:obj:`Connection` object wrapped around
3320 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003321 """
3322 # Now create the client side Connection. Similar boilerplate to the
3323 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003324 client_ctx = Context(TLSv1_METHOD)
3325 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
3326 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
3327 client_store = client_ctx.get_cert_store()
3328 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
3329 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
3330 client_ctx.check_privatekey()
3331 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003332 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003333 client_conn.set_connect_state()
3334 return client_conn
3335
3336
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003337 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003338 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003339 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003340 reading from the output of each and writing those bytes to the input of
3341 the other and in this way establish a connection and exchange
3342 application-level bytes with each other.
3343 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003344 server_conn = self._server(None)
3345 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003346
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003347 # There should be no key or nonces yet.
3348 self.assertIdentical(server_conn.master_key(), None)
3349 self.assertIdentical(server_conn.client_random(), None)
3350 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003351
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003352 # First, the handshake needs to happen. We'll deliver bytes back and
3353 # forth between the client and server until neither of them feels like
3354 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003355 self.assertIdentical(
3356 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003357
3358 # Now that the handshake is done, there should be a key and nonces.
3359 self.assertNotIdentical(server_conn.master_key(), None)
3360 self.assertNotIdentical(server_conn.client_random(), None)
3361 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04003362 self.assertEquals(server_conn.client_random(), client_conn.client_random())
3363 self.assertEquals(server_conn.server_random(), client_conn.server_random())
3364 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
3365 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003366
3367 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003368 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05003369
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003370 server_conn.write(important_message)
3371 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003372 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003373 (client_conn, important_message))
3374
3375 client_conn.write(important_message[::-1])
3376 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003377 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003378 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003379
3380
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003381 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003382 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003383 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003384
3385 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09003386 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003387 this test fails, there must be a problem outside the memory BIO
3388 code, as no memory BIO is involved here). Even though this isn't a
3389 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003390 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04003391 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003392
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003393 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05003394 client_conn.send(important_message)
3395 msg = server_conn.recv(1024)
3396 self.assertEqual(msg, important_message)
3397
3398 # Again in the other direction, just for fun.
3399 important_message = important_message[::-1]
3400 server_conn.send(important_message)
3401 msg = client_conn.recv(1024)
3402 self.assertEqual(msg, important_message)
3403
3404
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04003405 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003406 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003407 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
3408 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003409 """
3410 context = Context(SSLv3_METHOD)
3411 client = socket()
3412 clientSSL = Connection(context, client)
3413 self.assertRaises( TypeError, clientSSL.bio_read, 100)
3414 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04003415 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003416
3417
3418 def test_outgoingOverflow(self):
3419 """
3420 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09003421 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003422 returned and that many bytes from the beginning of the input can be
3423 read from the other end of the connection.
3424 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003425 server = self._server(None)
3426 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003427
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003428 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003429
3430 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003431 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003432 # Sanity check. We're trying to test what happens when the entire
3433 # input can't be sent. If the entire input was sent, this test is
3434 # meaningless.
3435 self.assertTrue(sent < size)
3436
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003437 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003438 self.assertIdentical(receiver, server)
3439
3440 # We can rely on all of these bytes being received at once because
3441 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
3442 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003443
3444
3445 def test_shutdown(self):
3446 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003447 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
3448 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003449 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003450 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003451 server.bio_shutdown()
3452 e = self.assertRaises(Error, server.recv, 1024)
3453 # We don't want WantReadError or ZeroReturnError or anything - it's a
3454 # handshake failure.
3455 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003456
3457
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003458 def test_unexpectedEndOfFile(self):
3459 """
3460 If the connection is lost before an orderly SSL shutdown occurs,
3461 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
3462 "Unexpected EOF".
3463 """
3464 server_conn, client_conn = self._loopback()
3465 client_conn.sock_shutdown(SHUT_RDWR)
3466 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
3467 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
3468
3469
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003470 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003471 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003472 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 -04003473
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003474 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003475 before the client and server are connected to each other. This
3476 function should specify a list of CAs for the server to send to the
3477 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09003478 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003479 times.
3480 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003481 server = self._server(None)
3482 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003483 self.assertEqual(client.get_client_ca_list(), [])
3484 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003485 ctx = server.get_context()
3486 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003487 self.assertEqual(client.get_client_ca_list(), [])
3488 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003489 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003490 self.assertEqual(client.get_client_ca_list(), expected)
3491 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003492
3493
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003494 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003495 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003496 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003497 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003498 """
3499 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003500 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
3501 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
3502 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003503
3504
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003505 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003506 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003507 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003508 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09003509 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003510 after the connection is set up.
3511 """
3512 def no_ca(ctx):
3513 ctx.set_client_ca_list([])
3514 return []
3515 self._check_client_ca_list(no_ca)
3516
3517
3518 def test_set_one_ca_list(self):
3519 """
3520 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003521 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003522 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003523 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003524 X509Name after the connection is set up.
3525 """
3526 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3527 cadesc = cacert.get_subject()
3528 def single_ca(ctx):
3529 ctx.set_client_ca_list([cadesc])
3530 return [cadesc]
3531 self._check_client_ca_list(single_ca)
3532
3533
3534 def test_set_multiple_ca_list(self):
3535 """
3536 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003537 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003538 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003539 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003540 X509Names after the connection is set up.
3541 """
3542 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3543 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3544
3545 sedesc = secert.get_subject()
3546 cldesc = clcert.get_subject()
3547
3548 def multiple_ca(ctx):
3549 L = [sedesc, cldesc]
3550 ctx.set_client_ca_list(L)
3551 return L
3552 self._check_client_ca_list(multiple_ca)
3553
3554
3555 def test_reset_ca_list(self):
3556 """
3557 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09003558 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003559 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003560 """
3561 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3562 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3563 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3564
3565 cadesc = cacert.get_subject()
3566 sedesc = secert.get_subject()
3567 cldesc = clcert.get_subject()
3568
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003569 def changed_ca(ctx):
3570 ctx.set_client_ca_list([sedesc, cldesc])
3571 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003572 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003573 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003574
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003575
3576 def test_mutated_ca_list(self):
3577 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003578 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003579 afterwards, this does not affect the list of CA names sent to the
3580 client.
3581 """
3582 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3583 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3584
3585 cadesc = cacert.get_subject()
3586 sedesc = secert.get_subject()
3587
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003588 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003589 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003590 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003591 L.append(sedesc)
3592 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003593 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003594
3595
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003596 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003597 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003598 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003599 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003600 """
3601 ctx = Context(TLSv1_METHOD)
3602 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003603 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003604 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003605 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003606
3607
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003608 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003609 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003610 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09003611 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003612 """
3613 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3614 cadesc = cacert.get_subject()
3615 def single_ca(ctx):
3616 ctx.add_client_ca(cacert)
3617 return [cadesc]
3618 self._check_client_ca_list(single_ca)
3619
3620
3621 def test_multiple_add_client_ca(self):
3622 """
3623 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09003624 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003625 """
3626 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3627 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3628
3629 cadesc = cacert.get_subject()
3630 sedesc = secert.get_subject()
3631
3632 def multiple_ca(ctx):
3633 ctx.add_client_ca(cacert)
3634 ctx.add_client_ca(secert)
3635 return [cadesc, sedesc]
3636 self._check_client_ca_list(multiple_ca)
3637
3638
3639 def test_set_and_add_client_ca(self):
3640 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003641 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
3642 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003643 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003644 """
3645 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3646 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3647 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3648
3649 cadesc = cacert.get_subject()
3650 sedesc = secert.get_subject()
3651 cldesc = clcert.get_subject()
3652
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003653 def mixed_set_add_ca(ctx):
3654 ctx.set_client_ca_list([cadesc, sedesc])
3655 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003656 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003657 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003658
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003659
3660 def test_set_after_add_client_ca(self):
3661 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003662 A call to :py:obj:`Context.set_client_ca_list` after a call to
3663 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003664 call with the names specified by the latter cal.
3665 """
3666 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3667 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3668 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3669
3670 cadesc = cacert.get_subject()
3671 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003672
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003673 def set_replaces_add_ca(ctx):
3674 ctx.add_client_ca(clcert)
3675 ctx.set_client_ca_list([cadesc])
3676 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003677 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003678 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003679
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003680
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003681
3682class ConnectionBIOTests(TestCase):
3683 """
3684 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3685 """
3686 def test_wantReadError(self):
3687 """
3688 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
3689 if there are no bytes available to be read from the BIO.
3690 """
3691 ctx = Context(TLSv1_METHOD)
3692 conn = Connection(ctx, None)
3693 self.assertRaises(WantReadError, conn.bio_read, 1024)
3694
3695
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003696 def test_buffer_size(self):
3697 """
3698 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3699 number of bytes to read and return.
3700 """
3701 ctx = Context(TLSv1_METHOD)
3702 conn = Connection(ctx, None)
3703 conn.set_connect_state()
3704 try:
3705 conn.do_handshake()
3706 except WantReadError:
3707 pass
3708 data = conn.bio_read(2)
3709 self.assertEqual(2, len(data))
3710
3711
3712 if not PY3:
3713 def test_buffer_size_long(self):
3714 """
3715 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3716 :py:obj:`long` as well as :py:obj:`int`.
3717 """
3718 ctx = Context(TLSv1_METHOD)
3719 conn = Connection(ctx, None)
3720 conn.set_connect_state()
3721 try:
3722 conn.do_handshake()
3723 except WantReadError:
3724 pass
3725 data = conn.bio_read(long(2))
3726 self.assertEqual(2, len(data))
3727
3728
3729
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003730
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003731class InfoConstantTests(TestCase):
3732 """
3733 Tests for assorted constants exposed for use in info callbacks.
3734 """
3735 def test_integers(self):
3736 """
3737 All of the info constants are integers.
3738
3739 This is a very weak test. It would be nice to have one that actually
3740 verifies that as certain info events happen, the value passed to the
3741 info callback matches up with the constant exposed by OpenSSL.SSL.
3742 """
3743 for const in [
3744 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3745 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3746 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3747 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3748 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
3749 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
3750
3751 self.assertTrue(isinstance(const, int))
3752
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003753
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003754if __name__ == '__main__':
3755 main()