blob: 2749a648783556de6e2d61476277102a303864e9 [file] [log] [blame]
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05001# Copyright (C) Jean-Paul Calderone
2# See LICENSE for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04003
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04004"""
Jonathan Ballet648875f2011-07-16 14:14:58 +09005Unit tests for :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04006"""
7
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05008from gc import collect, get_referrers
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02009from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE, ESHUTDOWN
Jean-Paul Calderone516c12c2015-04-13 20:34:57 -040010from sys import platform, getfilesystemencoding
Maximilian Hils1d95dea2015-08-17 19:27:20 +020011from socket import MSG_PEEK, SHUT_RDWR, error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040012from os import makedirs
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040013from os.path import join
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -040014from unittest import main
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040015from weakref import ref
Abraham Martinef063482015-03-25 14:06:24 +000016from warnings import catch_warnings, simplefilter
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050017
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -040018from six import PY3, text_type, u
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050019
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040020from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080021from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040022from OpenSSL.crypto import dump_privatekey, load_privatekey
23from OpenSSL.crypto import dump_certificate, load_certificate
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040024from OpenSSL.crypto import get_elliptic_curves
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040025
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040026from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
27from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040028from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040029from OpenSSL.SSL import (
30 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
31 TLSv1_1_METHOD, TLSv1_2_METHOD)
32from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040033from OpenSSL.SSL import (
34 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040035
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040036from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050037 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
38 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
39 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
40
41from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070042 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050043from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070044 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040045
Cory Benfieldba1820d2015-04-13 17:39:12 -040046from OpenSSL._util import lib as _lib
47
Jean-Paul Calderone17eca482015-04-13 20:31:07 -040048from OpenSSL.test.util import WARNING_TYPE_EXPECTED, NON_ASCII, TestCase, b
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040049from OpenSSL.test.test_crypto import (
Jean-Paul Calderoneda6399a2015-04-13 20:52:29 -040050 cleartextCertificatePEM, cleartextPrivateKeyPEM,
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040051 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
52 root_cert_pem)
53
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050054try:
55 from OpenSSL.SSL import OP_NO_QUERY_MTU
56except ImportError:
57 OP_NO_QUERY_MTU = None
58try:
59 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
60except ImportError:
61 OP_COOKIE_EXCHANGE = None
62try:
63 from OpenSSL.SSL import OP_NO_TICKET
64except ImportError:
65 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040066
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040067try:
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -040068 from OpenSSL.SSL import OP_NO_COMPRESSION
69except ImportError:
70 OP_NO_COMPRESSION = None
71
72try:
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040073 from OpenSSL.SSL import MODE_RELEASE_BUFFERS
74except ImportError:
75 MODE_RELEASE_BUFFERS = None
76
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040077try:
78 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
79except ImportError:
80 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
81
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040082from OpenSSL.SSL import (
83 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
84 SSL_ST_OK, SSL_ST_RENEGOTIATE,
85 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
86 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
87 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
88 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040089
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)
Jim Shaver46f28912015-05-29 19:32:16 -0400145
Rick Deanb1ccd562009-07-09 23:52:39 -0500146 return (server, client)
147
148
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400149
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400150def handshake(client, server):
151 conns = [client, server]
152 while conns:
153 for conn in conns:
154 try:
155 conn.do_handshake()
156 except WantReadError:
157 pass
158 else:
159 conns.remove(conn)
160
161
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400162def _create_certificate_chain():
163 """
164 Construct and return a chain of certificates.
165
166 1. A new self-signed certificate authority certificate (cacert)
167 2. A new intermediate certificate signed by cacert (icert)
168 3. A new server certificate signed by icert (scert)
169 """
170 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
171
172 # Step 1
173 cakey = PKey()
174 cakey.generate_key(TYPE_RSA, 512)
175 cacert = X509()
176 cacert.get_subject().commonName = "Authority Certificate"
177 cacert.set_issuer(cacert.get_subject())
178 cacert.set_pubkey(cakey)
179 cacert.set_notBefore(b("20000101000000Z"))
180 cacert.set_notAfter(b("20200101000000Z"))
181 cacert.add_extensions([caext])
182 cacert.set_serial_number(0)
183 cacert.sign(cakey, "sha1")
184
185 # Step 2
186 ikey = PKey()
187 ikey.generate_key(TYPE_RSA, 512)
188 icert = X509()
189 icert.get_subject().commonName = "Intermediate Certificate"
190 icert.set_issuer(cacert.get_subject())
191 icert.set_pubkey(ikey)
192 icert.set_notBefore(b("20000101000000Z"))
193 icert.set_notAfter(b("20200101000000Z"))
194 icert.add_extensions([caext])
195 icert.set_serial_number(0)
196 icert.sign(cakey, "sha1")
197
198 # Step 3
199 skey = PKey()
200 skey.generate_key(TYPE_RSA, 512)
201 scert = X509()
202 scert.get_subject().commonName = "Server Certificate"
203 scert.set_issuer(icert.get_subject())
204 scert.set_pubkey(skey)
205 scert.set_notBefore(b("20000101000000Z"))
206 scert.set_notAfter(b("20200101000000Z"))
207 scert.add_extensions([
208 X509Extension(b('basicConstraints'), True, b('CA:false'))])
209 scert.set_serial_number(0)
210 scert.sign(ikey, "sha1")
211
212 return [(cakey, cacert), (ikey, icert), (skey, scert)]
213
214
215
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400216class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400217 """
218 Helper mixin which defines methods for creating a connected socket pair and
219 for forcing two connected SSL sockets to talk to each other via memory BIOs.
220 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500221 def _loopbackClientFactory(self, socket):
222 client = Connection(Context(TLSv1_METHOD), socket)
223 client.set_connect_state()
224 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400225
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500226
227 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400228 ctx = Context(TLSv1_METHOD)
229 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
230 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500231 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400232 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500233 return server
234
235
236 def _loopback(self, serverFactory=None, clientFactory=None):
237 if serverFactory is None:
238 serverFactory = self._loopbackServerFactory
239 if clientFactory is None:
240 clientFactory = self._loopbackClientFactory
241
242 (server, client) = socket_pair()
243 server = serverFactory(server)
244 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400245
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400246 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400247
248 server.setblocking(True)
249 client.setblocking(True)
250 return server, client
251
252
253 def _interactInMemory(self, client_conn, server_conn):
254 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900255 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400256 objects. Copy bytes back and forth between their send/receive buffers
257 for as long as there is anything to copy. When there is nothing more
Jonathan Ballet648875f2011-07-16 14:14:58 +0900258 to copy, return :py:obj:`None`. If one of them actually manages to deliver
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400259 some application bytes, return a two-tuple of the connection from which
260 the bytes were read and the bytes themselves.
261 """
262 wrote = True
263 while wrote:
264 # Loop until neither side has anything to say
265 wrote = False
266
267 # Copy stuff from each side's send buffer to the other side's
268 # receive buffer.
269 for (read, write) in [(client_conn, server_conn),
270 (server_conn, client_conn)]:
271
272 # Give the side a chance to generate some more bytes, or
273 # succeed.
274 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400275 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400276 except WantReadError:
277 # It didn't succeed, so we'll hope it generated some
278 # output.
279 pass
280 else:
281 # It did succeed, so we'll stop now and let the caller deal
282 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400283 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400284
285 while True:
286 # Keep copying as long as there's more stuff there.
287 try:
288 dirty = read.bio_read(4096)
289 except WantReadError:
290 # Okay, nothing more waiting to be sent. Stop
291 # processing this send buffer.
292 break
293 else:
294 # Keep track of the fact that someone generated some
295 # output.
296 wrote = True
297 write.bio_write(dirty)
298
299
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400300 def _handshakeInMemory(self, client_conn, server_conn):
Jean-Paul Calderoneb2b40782014-05-06 08:47:40 -0400301 """
302 Perform the TLS handshake between two :py:class:`Connection` instances
303 connected to each other via memory BIOs.
304 """
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400305 client_conn.set_connect_state()
306 server_conn.set_accept_state()
307
308 for conn in [client_conn, server_conn]:
309 try:
310 conn.do_handshake()
311 except WantReadError:
312 pass
313
314 self._interactInMemory(client_conn, server_conn)
315
316
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400317
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400318class VersionTests(TestCase):
319 """
320 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900321 :py:obj:`OpenSSL.SSL.SSLeay_version` and
322 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400323 """
324 def test_OPENSSL_VERSION_NUMBER(self):
325 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900326 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400327 byte and the patch, fix, minor, and major versions in the
328 nibbles above that.
329 """
330 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
331
332
333 def test_SSLeay_version(self):
334 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900335 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400336 one of a number of version strings based on that indicator.
337 """
338 versions = {}
339 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
340 SSLEAY_PLATFORM, SSLEAY_DIR]:
341 version = SSLeay_version(t)
342 versions[version] = t
343 self.assertTrue(isinstance(version, bytes))
344 self.assertEqual(len(versions), 5)
345
346
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400347
348class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400349 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900350 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400351 """
352 def test_method(self):
353 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900354 :py:obj:`Context` can be instantiated with one of :py:obj:`SSLv2_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400355 :py:obj:`SSLv3_METHOD`, :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
356 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400357 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400358 methods = [
359 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
360 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400361 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400362
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400363
364 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
365 for meth in maybe:
366 try:
367 Context(meth)
368 except (Error, ValueError):
369 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
370 # don't. Difficult to say in advance.
371 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400372
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400373 self.assertRaises(TypeError, Context, "")
374 self.assertRaises(ValueError, Context, 10)
375
376
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500377 if not PY3:
378 def test_method_long(self):
379 """
380 On Python 2 :py:class:`Context` accepts values of type
381 :py:obj:`long` as well as :py:obj:`int`.
382 """
383 Context(long(TLSv1_METHOD))
384
385
386
Rick Deane15b1472009-07-09 15:53:42 -0500387 def test_type(self):
388 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900389 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400390 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500391 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400392 self.assertIdentical(Context, ContextType)
393 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500394
395
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400396 def test_use_privatekey(self):
397 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900398 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400399 """
400 key = PKey()
401 key.generate_key(TYPE_RSA, 128)
402 ctx = Context(TLSv1_METHOD)
403 ctx.use_privatekey(key)
404 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400405
406
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800407 def test_use_privatekey_file_missing(self):
408 """
409 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error`
410 when passed the name of a file which does not exist.
411 """
412 ctx = Context(TLSv1_METHOD)
413 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
414
415
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400416 def _use_privatekey_file_test(self, pemfile, filetype):
417 """
418 Verify that calling ``Context.use_privatekey_file`` with the given
419 arguments does not raise an exception.
420 """
421 key = PKey()
422 key.generate_key(TYPE_RSA, 128)
423
424 with open(pemfile, "wt") as pem:
425 pem.write(
426 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
427 )
428
429 ctx = Context(TLSv1_METHOD)
430 ctx.use_privatekey_file(pemfile, filetype)
431
432
433 def test_use_privatekey_file_bytes(self):
434 """
435 A private key can be specified from a file by passing a ``bytes``
436 instance giving the file name to ``Context.use_privatekey_file``.
437 """
438 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400439 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400440 FILETYPE_PEM,
441 )
442
443
444 def test_use_privatekey_file_unicode(self):
445 """
446 A private key can be specified from a file by passing a ``unicode``
447 instance giving the file name to ``Context.use_privatekey_file``.
448 """
449 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400450 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400451 FILETYPE_PEM,
452 )
453
454
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500455 if not PY3:
456 def test_use_privatekey_file_long(self):
457 """
458 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
459 filetype of type :py:obj:`long` as well as :py:obj:`int`.
460 """
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400461 self._use_privatekey_file_test(self.mktemp(), long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500462
463
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800464 def test_use_certificate_wrong_args(self):
465 """
466 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
467 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as an
468 argument.
469 """
470 ctx = Context(TLSv1_METHOD)
471 self.assertRaises(TypeError, ctx.use_certificate)
472 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
473 self.assertRaises(TypeError, ctx.use_certificate, X509(), "hello, world")
474
475
476 def test_use_certificate_uninitialized(self):
477 """
478 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
479 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
480 initialized (ie, which does not actually have any certificate data).
481 """
482 ctx = Context(TLSv1_METHOD)
483 self.assertRaises(Error, ctx.use_certificate, X509())
484
485
486 def test_use_certificate(self):
487 """
488 :py:obj:`Context.use_certificate` sets the certificate which will be
489 used to identify connections created using the context.
490 """
491 # TODO
492 # Hard to assert anything. But we could set a privatekey then ask
493 # OpenSSL if the cert and key agree using check_privatekey. Then as
494 # long as check_privatekey works right we're good...
495 ctx = Context(TLSv1_METHOD)
496 ctx.use_certificate(load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
497
498
499 def test_use_certificate_file_wrong_args(self):
500 """
501 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
502 called with zero arguments or more than two arguments, or if the first
503 argument is not a byte string or the second argumnent is not an integer.
504 """
505 ctx = Context(TLSv1_METHOD)
506 self.assertRaises(TypeError, ctx.use_certificate_file)
507 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile", object())
508 self.assertRaises(
509 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM, object())
510 self.assertRaises(
511 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
512 self.assertRaises(
513 TypeError, ctx.use_certificate_file, b"somefile", object())
514
515
516 def test_use_certificate_file_missing(self):
517 """
518 :py:obj:`Context.use_certificate_file` raises
519 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does not
520 exist.
521 """
522 ctx = Context(TLSv1_METHOD)
523 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
524
525
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400526 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800527 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400528 Verify that calling ``Context.use_certificate_file`` with the given
529 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800530 """
531 # TODO
532 # Hard to assert anything. But we could set a privatekey then ask
533 # OpenSSL if the cert and key agree using check_privatekey. Then as
534 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400535 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800536 pem_file.write(cleartextCertificatePEM)
537
538 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400539 ctx.use_certificate_file(certificate_file)
540
541
542 def test_use_certificate_file_bytes(self):
543 """
544 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
545 ``bytes`` filename) which will be used to identify connections created
546 using the context.
547 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400548 filename = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400549 self._use_certificate_file_test(filename)
550
551
552 def test_use_certificate_file_unicode(self):
553 """
554 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
555 ``bytes`` filename) which will be used to identify connections created
556 using the context.
557 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400558 filename = self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400559 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800560
561
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500562 if not PY3:
563 def test_use_certificate_file_long(self):
564 """
565 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
566 filetype of type :py:obj:`long` as well as :py:obj:`int`.
567 """
568 pem_filename = self.mktemp()
569 with open(pem_filename, "wb") as pem_file:
570 pem_file.write(cleartextCertificatePEM)
571
572 ctx = Context(TLSv1_METHOD)
573 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
574
575
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500576 def test_check_privatekey_valid(self):
577 """
578 :py:obj:`Context.check_privatekey` returns :py:obj:`None` if the
579 :py:obj:`Context` instance has been configured to use a matched key and
580 certificate pair.
581 """
582 key = load_privatekey(FILETYPE_PEM, client_key_pem)
583 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
584 context = Context(TLSv1_METHOD)
585 context.use_privatekey(key)
586 context.use_certificate(cert)
587 self.assertIs(None, context.check_privatekey())
588
589
590 def test_check_privatekey_invalid(self):
591 """
592 :py:obj:`Context.check_privatekey` raises :py:obj:`Error` if the
593 :py:obj:`Context` instance has been configured to use a key and
594 certificate pair which don't relate to each other.
595 """
596 key = load_privatekey(FILETYPE_PEM, client_key_pem)
597 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
598 context = Context(TLSv1_METHOD)
599 context.use_privatekey(key)
600 context.use_certificate(cert)
601 self.assertRaises(Error, context.check_privatekey)
602
603
604 def test_check_privatekey_wrong_args(self):
605 """
606 :py:obj:`Context.check_privatekey` raises :py:obj:`TypeError` if called
607 with other than no arguments.
608 """
609 context = Context(TLSv1_METHOD)
610 self.assertRaises(TypeError, context.check_privatekey, object())
611
612
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400613 def test_set_app_data_wrong_args(self):
614 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900615 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called with other than
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400616 one argument.
617 """
618 context = Context(TLSv1_METHOD)
619 self.assertRaises(TypeError, context.set_app_data)
620 self.assertRaises(TypeError, context.set_app_data, None, None)
621
622
623 def test_get_app_data_wrong_args(self):
624 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900625 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400626 arguments.
627 """
628 context = Context(TLSv1_METHOD)
629 self.assertRaises(TypeError, context.get_app_data, None)
630
631
632 def test_app_data(self):
633 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900634 :py:obj:`Context.set_app_data` stores an object for later retrieval using
635 :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400636 """
637 app_data = object()
638 context = Context(TLSv1_METHOD)
639 context.set_app_data(app_data)
640 self.assertIdentical(context.get_app_data(), app_data)
641
642
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400643 def test_set_options_wrong_args(self):
644 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900645 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with the wrong
646 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400647 """
648 context = Context(TLSv1_METHOD)
649 self.assertRaises(TypeError, context.set_options)
650 self.assertRaises(TypeError, context.set_options, None)
651 self.assertRaises(TypeError, context.set_options, 1, None)
652
653
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500654 def test_set_options(self):
655 """
656 :py:obj:`Context.set_options` returns the new options value.
657 """
658 context = Context(TLSv1_METHOD)
659 options = context.set_options(OP_NO_SSLv2)
660 self.assertTrue(OP_NO_SSLv2 & options)
661
662
663 if not PY3:
664 def test_set_options_long(self):
665 """
666 On Python 2 :py:obj:`Context.set_options` accepts values of type
667 :py:obj:`long` as well as :py:obj:`int`.
668 """
669 context = Context(TLSv1_METHOD)
670 options = context.set_options(long(OP_NO_SSLv2))
671 self.assertTrue(OP_NO_SSLv2 & options)
672
673
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300674 def test_set_mode_wrong_args(self):
675 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400676 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with the wrong
677 number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300678 """
679 context = Context(TLSv1_METHOD)
680 self.assertRaises(TypeError, context.set_mode)
681 self.assertRaises(TypeError, context.set_mode, None)
682 self.assertRaises(TypeError, context.set_mode, 1, None)
683
684
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400685 if MODE_RELEASE_BUFFERS is not None:
686 def test_set_mode(self):
687 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400688 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the newly
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400689 set mode.
690 """
691 context = Context(TLSv1_METHOD)
692 self.assertTrue(
693 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500694
695 if not PY3:
696 def test_set_mode_long(self):
697 """
698 On Python 2 :py:obj:`Context.set_mode` accepts values of type
699 :py:obj:`long` as well as :py:obj:`int`.
700 """
701 context = Context(TLSv1_METHOD)
702 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
703 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400704 else:
705 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
706
707
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400708 def test_set_timeout_wrong_args(self):
709 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900710 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with the wrong
711 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400712 """
713 context = Context(TLSv1_METHOD)
714 self.assertRaises(TypeError, context.set_timeout)
715 self.assertRaises(TypeError, context.set_timeout, None)
716 self.assertRaises(TypeError, context.set_timeout, 1, None)
717
718
719 def test_get_timeout_wrong_args(self):
720 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900721 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400722 """
723 context = Context(TLSv1_METHOD)
724 self.assertRaises(TypeError, context.get_timeout, None)
725
726
727 def test_timeout(self):
728 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900729 :py:obj:`Context.set_timeout` sets the session timeout for all connections
730 created using the context object. :py:obj:`Context.get_timeout` retrieves this
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400731 value.
732 """
733 context = Context(TLSv1_METHOD)
734 context.set_timeout(1234)
735 self.assertEquals(context.get_timeout(), 1234)
736
737
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500738 if not PY3:
739 def test_timeout_long(self):
740 """
741 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
742 `long` as well as int.
743 """
744 context = Context(TLSv1_METHOD)
745 context.set_timeout(long(1234))
746 self.assertEquals(context.get_timeout(), 1234)
747
748
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400749 def test_set_verify_depth_wrong_args(self):
750 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900751 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called with the wrong
752 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400753 """
754 context = Context(TLSv1_METHOD)
755 self.assertRaises(TypeError, context.set_verify_depth)
756 self.assertRaises(TypeError, context.set_verify_depth, None)
757 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
758
759
760 def test_get_verify_depth_wrong_args(self):
761 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900762 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400763 """
764 context = Context(TLSv1_METHOD)
765 self.assertRaises(TypeError, context.get_verify_depth, None)
766
767
768 def test_verify_depth(self):
769 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900770 :py:obj:`Context.set_verify_depth` sets the number of certificates in a chain
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400771 to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900772 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400773 """
774 context = Context(TLSv1_METHOD)
775 context.set_verify_depth(11)
776 self.assertEquals(context.get_verify_depth(), 11)
777
778
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500779 if not PY3:
780 def test_verify_depth_long(self):
781 """
782 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
783 type `long` as well as int.
784 """
785 context = Context(TLSv1_METHOD)
786 context.set_verify_depth(long(11))
787 self.assertEquals(context.get_verify_depth(), 11)
788
789
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400790 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400791 """
792 Write a new private key out to a new file, encrypted using the given
793 passphrase. Return the path to the new file.
794 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400795 key = PKey()
796 key.generate_key(TYPE_RSA, 128)
797 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400798 fObj = open(pemFile, 'w')
799 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
800 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400801 fObj.close()
802 return pemFile
803
804
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400805 def test_set_passwd_cb_wrong_args(self):
806 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900807 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called with the
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400808 wrong arguments or with a non-callable first argument.
809 """
810 context = Context(TLSv1_METHOD)
811 self.assertRaises(TypeError, context.set_passwd_cb)
812 self.assertRaises(TypeError, context.set_passwd_cb, None)
813 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
814
815
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400816 def test_set_passwd_cb(self):
817 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900818 :py:obj:`Context.set_passwd_cb` accepts a callable which will be invoked when
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400819 a private key is loaded from an encrypted PEM.
820 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400821 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400822 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400823 calledWith = []
824 def passphraseCallback(maxlen, verify, extra):
825 calledWith.append((maxlen, verify, extra))
826 return passphrase
827 context = Context(TLSv1_METHOD)
828 context.set_passwd_cb(passphraseCallback)
829 context.use_privatekey_file(pemFile)
830 self.assertTrue(len(calledWith), 1)
831 self.assertTrue(isinstance(calledWith[0][0], int))
832 self.assertTrue(isinstance(calledWith[0][1], int))
833 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400834
835
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400836 def test_passwd_callback_exception(self):
837 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900838 :py:obj:`Context.use_privatekey_file` propagates any exception raised by the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400839 passphrase callback.
840 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400841 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400842 def passphraseCallback(maxlen, verify, extra):
843 raise RuntimeError("Sorry, I am a fail.")
844
845 context = Context(TLSv1_METHOD)
846 context.set_passwd_cb(passphraseCallback)
847 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
848
849
850 def test_passwd_callback_false(self):
851 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900852 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400853 passphrase callback returns a false value.
854 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400855 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400856 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500857 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400858
859 context = Context(TLSv1_METHOD)
860 context.set_passwd_cb(passphraseCallback)
861 self.assertRaises(Error, context.use_privatekey_file, pemFile)
862
863
864 def test_passwd_callback_non_string(self):
865 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900866 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400867 passphrase callback returns a true non-string value.
868 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400869 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400870 def passphraseCallback(maxlen, verify, extra):
871 return 10
872
873 context = Context(TLSv1_METHOD)
874 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800875 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400876
877
878 def test_passwd_callback_too_long(self):
879 """
880 If the passphrase returned by the passphrase callback returns a string
881 longer than the indicated maximum length, it is truncated.
882 """
883 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400884 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400885 pemFile = self._write_encrypted_pem(passphrase)
886 def passphraseCallback(maxlen, verify, extra):
887 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400888 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400889
890 context = Context(TLSv1_METHOD)
891 context.set_passwd_cb(passphraseCallback)
892 # This shall succeed because the truncated result is the correct
893 # passphrase.
894 context.use_privatekey_file(pemFile)
895
896
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400897 def test_set_info_callback(self):
898 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900899 :py:obj:`Context.set_info_callback` accepts a callable which will be invoked
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400900 when certain information about an SSL connection is available.
901 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500902 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400903
904 clientSSL = Connection(Context(TLSv1_METHOD), client)
905 clientSSL.set_connect_state()
906
907 called = []
908 def info(conn, where, ret):
909 called.append((conn, where, ret))
910 context = Context(TLSv1_METHOD)
911 context.set_info_callback(info)
912 context.use_certificate(
913 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
914 context.use_privatekey(
915 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
916
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400917 serverSSL = Connection(context, server)
918 serverSSL.set_accept_state()
919
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500920 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400921
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500922 # The callback must always be called with a Connection instance as the
923 # first argument. It would probably be better to split this into
924 # separate tests for client and server side info callbacks so we could
925 # assert it is called with the right Connection instance. It would
926 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500927 notConnections = [
928 conn for (conn, where, ret) in called
929 if not isinstance(conn, Connection)]
930 self.assertEqual(
931 [], notConnections,
932 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400933
934
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400935 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400936 """
937 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400938 its :py:obj:`load_verify_locations` method with the given arguments.
939 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400940 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500941 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400942
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400943 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400944 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400945 # Require that the server certificate verify properly or the
946 # connection will fail.
947 clientContext.set_verify(
948 VERIFY_PEER,
949 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
950
951 clientSSL = Connection(clientContext, client)
952 clientSSL.set_connect_state()
953
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400954 serverContext = Context(TLSv1_METHOD)
955 serverContext.use_certificate(
956 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
957 serverContext.use_privatekey(
958 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
959
960 serverSSL = Connection(serverContext, server)
961 serverSSL.set_accept_state()
962
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400963 # Without load_verify_locations above, the handshake
964 # will fail:
965 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
966 # 'certificate verify failed')]
967 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400968
969 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400970 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400971
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500972
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400973 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400974 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400975 Verify that if path to a file containing a certificate is passed to
976 ``Context.load_verify_locations`` for the ``cafile`` parameter, that
977 certificate is used as a trust root for the purposes of verifying
978 connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400979 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400980 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400981 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400982 fObj.close()
983
984 self._load_verify_locations_test(cafile)
985
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400986
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400987 def test_load_verify_bytes_cafile(self):
988 """
989 :py:obj:`Context.load_verify_locations` accepts a file name as a
990 ``bytes`` instance and uses the certificates within for verification
991 purposes.
992 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400993 cafile = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400994 self._load_verify_cafile(cafile)
995
996
997 def test_load_verify_unicode_cafile(self):
998 """
999 :py:obj:`Context.load_verify_locations` accepts a file name as a
1000 ``unicode`` instance and uses the certificates within for verification
1001 purposes.
1002 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001003 self._load_verify_cafile(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001004 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001005 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001006
1007
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001008 def test_load_verify_invalid_file(self):
1009 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001010 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when passed a
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001011 non-existent cafile.
1012 """
1013 clientContext = Context(TLSv1_METHOD)
1014 self.assertRaises(
1015 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001016
1017
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001018 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001019 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001020 Verify that if path to a directory containing certificate files is
1021 passed to ``Context.load_verify_locations`` for the ``capath``
1022 parameter, those certificates are used as trust roots for the purposes
1023 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001024 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001025 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001026 # Hash values computed manually with c_rehash to avoid depending on
1027 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1028 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001029 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001030 cafile = join_bytes_or_unicode(capath, name)
1031 with open(cafile, 'w') as fObj:
1032 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001033
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001034 self._load_verify_locations_test(None, capath)
1035
1036
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001037 def test_load_verify_directory_bytes_capath(self):
1038 """
1039 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1040 ``bytes`` instance and uses the certificates within for verification
1041 purposes.
1042 """
1043 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001044 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001045 )
1046
1047
1048 def test_load_verify_directory_unicode_capath(self):
1049 """
1050 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1051 ``unicode`` instance and uses the certificates within for verification
1052 purposes.
1053 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001054 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001055 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001056 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001057
1058
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001059 def test_load_verify_locations_wrong_args(self):
1060 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001061 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if called with
1062 the wrong number of arguments or with non-:py:obj:`str` arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001063 """
1064 context = Context(TLSv1_METHOD)
1065 self.assertRaises(TypeError, context.load_verify_locations)
1066 self.assertRaises(TypeError, context.load_verify_locations, object())
1067 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
1068 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
1069
1070
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001071 if platform == "win32":
1072 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001073 "See LP#404343 and LP#404344."
1074 else:
1075 def test_set_default_verify_paths(self):
1076 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001077 :py:obj:`Context.set_default_verify_paths` causes the platform-specific CA
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001078 certificate locations to be used for verification purposes.
1079 """
1080 # Testing this requires a server with a certificate signed by one of
1081 # the CAs in the platform CA location. Getting one of those costs
1082 # money. Fortunately (or unfortunately, depending on your
1083 # perspective), it's easy to think of a public server on the
1084 # internet which has such a certificate. Connecting to the network
1085 # in a unit test is bad, but it's the only way I can think of to
1086 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001087
Alex Gaynorb586da32014-11-15 09:22:21 -08001088 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
1089 context = Context(TLSv1_METHOD)
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001090 context.set_default_verify_paths()
1091 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02001092 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001093 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001094
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001095 client = socket()
1096 client.connect(('verisign.com', 443))
1097 clientSSL = Connection(context, client)
1098 clientSSL.set_connect_state()
1099 clientSSL.do_handshake()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001100 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001101 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001102
1103
1104 def test_set_default_verify_paths_signature(self):
1105 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001106 :py:obj:`Context.set_default_verify_paths` takes no arguments and raises
1107 :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001108 """
1109 context = Context(TLSv1_METHOD)
1110 self.assertRaises(TypeError, context.set_default_verify_paths, None)
1111 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
1112 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001113
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001114
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001115 def test_add_extra_chain_cert_invalid_cert(self):
1116 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001117 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if called with
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001118 other than one argument or if called with an object which is not an
Jonathan Ballet648875f2011-07-16 14:14:58 +09001119 instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001120 """
1121 context = Context(TLSv1_METHOD)
1122 self.assertRaises(TypeError, context.add_extra_chain_cert)
1123 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
1124 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
1125
1126
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001127 def _handshake_test(self, serverContext, clientContext):
1128 """
1129 Verify that a client and server created with the given contexts can
1130 successfully handshake and communicate.
1131 """
1132 serverSocket, clientSocket = socket_pair()
1133
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001134 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001135 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001136
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001137 client = Connection(clientContext, clientSocket)
1138 client.set_connect_state()
1139
1140 # Make them talk to each other.
1141 # self._interactInMemory(client, server)
1142 for i in range(3):
1143 for s in [client, server]:
1144 try:
1145 s.do_handshake()
1146 except WantReadError:
1147 pass
1148
1149
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001150 def test_set_verify_callback_connection_argument(self):
1151 """
1152 The first argument passed to the verify callback is the
1153 :py:class:`Connection` instance for which verification is taking place.
1154 """
1155 serverContext = Context(TLSv1_METHOD)
1156 serverContext.use_privatekey(
1157 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1158 serverContext.use_certificate(
1159 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1160 serverConnection = Connection(serverContext, None)
1161
1162 class VerifyCallback(object):
1163 def callback(self, connection, *args):
1164 self.connection = connection
1165 return 1
1166
1167 verify = VerifyCallback()
1168 clientContext = Context(TLSv1_METHOD)
1169 clientContext.set_verify(VERIFY_PEER, verify.callback)
1170 clientConnection = Connection(clientContext, None)
1171 clientConnection.set_connect_state()
1172
1173 self._handshakeInMemory(clientConnection, serverConnection)
1174
1175 self.assertIdentical(verify.connection, clientConnection)
1176
1177
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001178 def test_set_verify_callback_exception(self):
1179 """
1180 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1181 exception, verification fails and the exception is propagated to the
1182 caller of :py:obj:`Connection.do_handshake`.
1183 """
1184 serverContext = Context(TLSv1_METHOD)
1185 serverContext.use_privatekey(
1186 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1187 serverContext.use_certificate(
1188 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1189
1190 clientContext = Context(TLSv1_METHOD)
1191 def verify_callback(*args):
1192 raise Exception("silly verify failure")
1193 clientContext.set_verify(VERIFY_PEER, verify_callback)
1194
1195 exc = self.assertRaises(
1196 Exception, self._handshake_test, serverContext, clientContext)
1197 self.assertEqual("silly verify failure", str(exc))
1198
1199
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001200 def test_add_extra_chain_cert(self):
1201 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001202 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509`
1203 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001204
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001205 See :py:obj:`_create_certificate_chain` for the details of the
1206 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001207
1208 The chain is tested by starting a server with scert and connecting
1209 to it with a client which trusts cacert and requires verification to
1210 succeed.
1211 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001212 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001213 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1214
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001215 # Dump the CA certificate to a file because that's the only way to load
1216 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001217 for cert, name in [(cacert, 'ca.pem'),
1218 (icert, 'i.pem'),
1219 (scert, 's.pem')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001220 with open(join(self.tmpdir, name), 'w') as f:
1221 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001222
Hynek Schlawack1902c012015-04-16 15:06:41 -04001223 for key, name in [(cakey, 'ca.key'),
1224 (ikey, 'i.key'),
1225 (skey, 's.key')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001226 with open(join(self.tmpdir, name), 'w') as f:
1227 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001228
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001229 # Create the server context
1230 serverContext = Context(TLSv1_METHOD)
1231 serverContext.use_privatekey(skey)
1232 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001233 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001234 serverContext.add_extra_chain_cert(icert)
1235
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001236 # Create the client
1237 clientContext = Context(TLSv1_METHOD)
1238 clientContext.set_verify(
1239 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001240 clientContext.load_verify_locations(join(self.tmpdir, "ca.pem"))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001241
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001242 # Try it out.
1243 self._handshake_test(serverContext, clientContext)
1244
1245
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001246 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001247 """
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001248 Verify that :py:obj:`Context.use_certificate_chain_file` reads a
1249 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001250
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001251 The chain is tested by starting a server with scert and connecting to
1252 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001253 succeed.
1254 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001255 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001256 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1257
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001258 makedirs(certdir)
1259
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001260 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1261 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001262
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001263 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001264 with open(chainFile, 'wb') as fObj:
1265 # Most specific to least general.
1266 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1267 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1268 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1269
1270 with open(caFile, 'w') as fObj:
1271 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001272
1273 serverContext = Context(TLSv1_METHOD)
1274 serverContext.use_certificate_chain_file(chainFile)
1275 serverContext.use_privatekey(skey)
1276
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001277 clientContext = Context(TLSv1_METHOD)
1278 clientContext.set_verify(
1279 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001280 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001281
1282 self._handshake_test(serverContext, clientContext)
1283
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001284
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001285 def test_use_certificate_chain_file_bytes(self):
1286 """
1287 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1288 an instance of ``bytes``) to specify additional certificates to use to
1289 construct and verify a trust chain.
1290 """
1291 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001292 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001293 )
1294
1295
1296 def test_use_certificate_chain_file_unicode(self):
1297 """
1298 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1299 an instance of ``unicode``) to specify additional certificates to use
1300 to construct and verify a trust chain.
1301 """
1302 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001303 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001304 )
1305
1306
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001307 def test_use_certificate_chain_file_wrong_args(self):
1308 """
1309 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1310 if passed zero or more than one argument or when passed a non-byte
1311 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error` when
1312 passed a bad chain file name (for example, the name of a file which does
1313 not exist).
1314 """
1315 context = Context(TLSv1_METHOD)
1316 self.assertRaises(TypeError, context.use_certificate_chain_file)
1317 self.assertRaises(TypeError, context.use_certificate_chain_file, object())
1318 self.assertRaises(TypeError, context.use_certificate_chain_file, b"foo", object())
1319
1320 self.assertRaises(Error, context.use_certificate_chain_file, self.mktemp())
1321
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001322 # XXX load_client_ca
1323 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001324
1325 def test_get_verify_mode_wrong_args(self):
1326 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001327 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001328 arguments.
1329 """
1330 context = Context(TLSv1_METHOD)
1331 self.assertRaises(TypeError, context.get_verify_mode, None)
1332
1333
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001334 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001335 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001336 :py:obj:`Context.get_verify_mode` returns the verify mode flags previously
1337 passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001338 """
1339 context = Context(TLSv1_METHOD)
1340 self.assertEquals(context.get_verify_mode(), 0)
1341 context.set_verify(
1342 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1343 self.assertEquals(
1344 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1345
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001346
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001347 if not PY3:
1348 def test_set_verify_mode_long(self):
1349 """
1350 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1351 type :py:obj:`long` as well as :py:obj:`int`.
1352 """
1353 context = Context(TLSv1_METHOD)
1354 self.assertEquals(context.get_verify_mode(), 0)
1355 context.set_verify(
1356 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None)
1357 self.assertEquals(
1358 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1359
1360
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001361 def test_load_tmp_dh_wrong_args(self):
1362 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001363 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
1364 number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001365 """
1366 context = Context(TLSv1_METHOD)
1367 self.assertRaises(TypeError, context.load_tmp_dh)
1368 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1369 self.assertRaises(TypeError, context.load_tmp_dh, object())
1370
1371
1372 def test_load_tmp_dh_missing_file(self):
1373 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001374 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the specified file
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001375 does not exist.
1376 """
1377 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001378 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001379
1380
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001381 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001382 """
1383 Verify that calling ``Context.load_tmp_dh`` with the given filename
1384 does not raise an exception.
1385 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001386 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001387 with open(dhfilename, "w") as dhfile:
1388 dhfile.write(dhparam)
1389
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001390 context.load_tmp_dh(dhfilename)
1391 # XXX What should I assert here? -exarkun
1392
1393
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001394 def test_load_tmp_dh_bytes(self):
1395 """
1396 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1397 specified file (given as ``bytes``).
1398 """
1399 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001400 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001401 )
1402
1403
1404 def test_load_tmp_dh_unicode(self):
1405 """
1406 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1407 specified file (given as ``unicode``).
1408 """
1409 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001410 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001411 )
1412
1413
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001414 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001415 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001416 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001417 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001418 """
1419 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001420 for curve in get_elliptic_curves():
1421 # The only easily "assertable" thing is that it does not raise an
1422 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001423 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001424
1425
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001426 def test_set_cipher_list_bytes(self):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001427 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001428 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
1429 ciphers which connections created with the context object will be able
1430 to choose from.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001431 """
1432 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001433 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001434 conn = Connection(context, None)
1435 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001436
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001437
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001438 def test_set_cipher_list_text(self):
1439 """
1440 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
1441 the ciphers which connections created with the context object will be
1442 able to choose from.
1443 """
1444 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -05001445 context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001446 conn = Connection(context, None)
1447 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
1448
1449
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001450 def test_set_cipher_list_wrong_args(self):
1451 """
Jean-Paul Calderone17044832014-01-18 10:20:11 -05001452 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
1453 passed zero arguments or more than one argument or when passed a
1454 non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001455 passed an incorrect cipher list string.
1456 """
1457 context = Context(TLSv1_METHOD)
1458 self.assertRaises(TypeError, context.set_cipher_list)
1459 self.assertRaises(TypeError, context.set_cipher_list, object())
1460 self.assertRaises(TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object())
1461
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001462 self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001463
1464
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001465 def test_set_session_cache_mode_wrong_args(self):
1466 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001467 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1468 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001469 """
1470 context = Context(TLSv1_METHOD)
1471 self.assertRaises(TypeError, context.set_session_cache_mode)
1472 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1473
1474
1475 def test_get_session_cache_mode_wrong_args(self):
1476 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001477 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1478 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001479 """
1480 context = Context(TLSv1_METHOD)
1481 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1482
1483
1484 def test_session_cache_mode(self):
1485 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001486 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1487 cached. The setting can be retrieved via
1488 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001489 """
1490 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001491 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001492 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1493 self.assertEqual(SESS_CACHE_OFF, off)
1494 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1495
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001496 if not PY3:
1497 def test_session_cache_mode_long(self):
1498 """
1499 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1500 of type :py:obj:`long` as well as :py:obj:`int`.
1501 """
1502 context = Context(TLSv1_METHOD)
1503 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1504 self.assertEqual(
1505 SESS_CACHE_BOTH, context.get_session_cache_mode())
1506
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001507
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001508 def test_get_cert_store(self):
1509 """
1510 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store` instance.
1511 """
1512 context = Context(TLSv1_METHOD)
1513 store = context.get_cert_store()
1514 self.assertIsInstance(store, X509Store)
1515
1516
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001517
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001518class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1519 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001520 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
1521 :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001522 """
1523 def test_wrong_args(self):
1524 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001525 :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001526 with other than one argument.
1527 """
1528 context = Context(TLSv1_METHOD)
1529 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1530 self.assertRaises(
1531 TypeError, context.set_tlsext_servername_callback, 1, 2)
1532
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001533
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001534 def test_old_callback_forgotten(self):
1535 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001536 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001537 callback, the one it replaces is dereferenced.
1538 """
1539 def callback(connection):
1540 pass
1541
1542 def replacement(connection):
1543 pass
1544
1545 context = Context(TLSv1_METHOD)
1546 context.set_tlsext_servername_callback(callback)
1547
1548 tracker = ref(callback)
1549 del callback
1550
1551 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001552
1553 # One run of the garbage collector happens to work on CPython. PyPy
1554 # doesn't collect the underlying object until a second run for whatever
1555 # reason. That's fine, it still demonstrates our code has properly
1556 # dropped the reference.
1557 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001558 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001559
1560 callback = tracker()
1561 if callback is not None:
1562 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001563 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001564 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001565
1566
1567 def test_no_servername(self):
1568 """
1569 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001570 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
1571 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001572 """
1573 args = []
1574 def servername(conn):
1575 args.append((conn, conn.get_servername()))
1576 context = Context(TLSv1_METHOD)
1577 context.set_tlsext_servername_callback(servername)
1578
1579 # Lose our reference to it. The Context is responsible for keeping it
1580 # alive now.
1581 del servername
1582 collect()
1583
1584 # Necessary to actually accept the connection
1585 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1586 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1587
1588 # Do a little connection to trigger the logic
1589 server = Connection(context, None)
1590 server.set_accept_state()
1591
1592 client = Connection(Context(TLSv1_METHOD), None)
1593 client.set_connect_state()
1594
1595 self._interactInMemory(server, client)
1596
1597 self.assertEqual([(server, None)], args)
1598
1599
1600 def test_servername(self):
1601 """
1602 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +09001603 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
1604 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001605 """
1606 args = []
1607 def servername(conn):
1608 args.append((conn, conn.get_servername()))
1609 context = Context(TLSv1_METHOD)
1610 context.set_tlsext_servername_callback(servername)
1611
1612 # Necessary to actually accept the connection
1613 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1614 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1615
1616 # Do a little connection to trigger the logic
1617 server = Connection(context, None)
1618 server.set_accept_state()
1619
1620 client = Connection(Context(TLSv1_METHOD), None)
1621 client.set_connect_state()
1622 client.set_tlsext_host_name(b("foo1.example.com"))
1623
1624 self._interactInMemory(server, client)
1625
1626 self.assertEqual([(server, b("foo1.example.com"))], args)
1627
1628
Cory Benfield84a121e2014-03-31 20:30:25 +01001629class NextProtoNegotiationTests(TestCase, _LoopbackMixin):
1630 """
1631 Test for Next Protocol Negotiation in PyOpenSSL.
1632 """
Cory Benfieldba1820d2015-04-13 17:39:12 -04001633 if _lib.Cryptography_HAS_NEXTPROTONEG:
1634 def test_npn_success(self):
1635 """
1636 Tests that clients and servers that agree on the negotiated next
1637 protocol can correct establish a connection, and that the agreed
1638 protocol is reported by the connections.
1639 """
1640 advertise_args = []
1641 select_args = []
1642 def advertise(conn):
1643 advertise_args.append((conn,))
1644 return [b'http/1.1', b'spdy/2']
1645 def select(conn, options):
1646 select_args.append((conn, options))
1647 return b'spdy/2'
Cory Benfield84a121e2014-03-31 20:30:25 +01001648
Cory Benfieldba1820d2015-04-13 17:39:12 -04001649 server_context = Context(TLSv1_METHOD)
1650 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001651
Cory Benfieldba1820d2015-04-13 17:39:12 -04001652 client_context = Context(TLSv1_METHOD)
1653 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001654
Cory Benfieldba1820d2015-04-13 17:39:12 -04001655 # Necessary to actually accept the connection
1656 server_context.use_privatekey(
1657 load_privatekey(FILETYPE_PEM, server_key_pem))
1658 server_context.use_certificate(
1659 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001660
Cory Benfieldba1820d2015-04-13 17:39:12 -04001661 # Do a little connection to trigger the logic
1662 server = Connection(server_context, None)
1663 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001664
Cory Benfieldba1820d2015-04-13 17:39:12 -04001665 client = Connection(client_context, None)
1666 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001667
Cory Benfieldba1820d2015-04-13 17:39:12 -04001668 self._interactInMemory(server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001669
Cory Benfieldba1820d2015-04-13 17:39:12 -04001670 self.assertEqual([(server,)], advertise_args)
1671 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001672
Cory Benfieldba1820d2015-04-13 17:39:12 -04001673 self.assertEqual(server.get_next_proto_negotiated(), b'spdy/2')
1674 self.assertEqual(client.get_next_proto_negotiated(), b'spdy/2')
Cory Benfield84a121e2014-03-31 20:30:25 +01001675
1676
Cory Benfieldba1820d2015-04-13 17:39:12 -04001677 def test_npn_client_fail(self):
1678 """
1679 Tests that when clients and servers cannot agree on what protocol
1680 to use next that the TLS connection does not get established.
1681 """
1682 advertise_args = []
1683 select_args = []
1684 def advertise(conn):
1685 advertise_args.append((conn,))
1686 return [b'http/1.1', b'spdy/2']
1687 def select(conn, options):
1688 select_args.append((conn, options))
1689 return b''
Cory Benfield84a121e2014-03-31 20:30:25 +01001690
Cory Benfieldba1820d2015-04-13 17:39:12 -04001691 server_context = Context(TLSv1_METHOD)
1692 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001693
Cory Benfieldba1820d2015-04-13 17:39:12 -04001694 client_context = Context(TLSv1_METHOD)
1695 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001696
Cory Benfieldba1820d2015-04-13 17:39:12 -04001697 # Necessary to actually accept the connection
1698 server_context.use_privatekey(
1699 load_privatekey(FILETYPE_PEM, server_key_pem))
1700 server_context.use_certificate(
1701 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001702
Cory Benfieldba1820d2015-04-13 17:39:12 -04001703 # Do a little connection to trigger the logic
1704 server = Connection(server_context, None)
1705 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001706
Cory Benfieldba1820d2015-04-13 17:39:12 -04001707 client = Connection(client_context, None)
1708 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001709
Cory Benfieldba1820d2015-04-13 17:39:12 -04001710 # If the client doesn't return anything, the connection will fail.
1711 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001712
Cory Benfieldba1820d2015-04-13 17:39:12 -04001713 self.assertEqual([(server,)], advertise_args)
1714 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001715
1716
Cory Benfieldba1820d2015-04-13 17:39:12 -04001717 def test_npn_select_error(self):
1718 """
1719 Test that we can handle exceptions in the select callback. If
1720 select fails it should be fatal to the connection.
1721 """
1722 advertise_args = []
1723 def advertise(conn):
1724 advertise_args.append((conn,))
1725 return [b'http/1.1', b'spdy/2']
1726 def select(conn, options):
1727 raise TypeError
Cory Benfield0ea76e72015-03-22 09:05:28 +00001728
Cory Benfieldba1820d2015-04-13 17:39:12 -04001729 server_context = Context(TLSv1_METHOD)
1730 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001731
Cory Benfieldba1820d2015-04-13 17:39:12 -04001732 client_context = Context(TLSv1_METHOD)
1733 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001734
Cory Benfieldba1820d2015-04-13 17:39:12 -04001735 # Necessary to actually accept the connection
1736 server_context.use_privatekey(
1737 load_privatekey(FILETYPE_PEM, server_key_pem))
1738 server_context.use_certificate(
1739 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001740
Cory Benfieldba1820d2015-04-13 17:39:12 -04001741 # Do a little connection to trigger the logic
1742 server = Connection(server_context, None)
1743 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001744
Cory Benfieldba1820d2015-04-13 17:39:12 -04001745 client = Connection(client_context, None)
1746 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001747
Cory Benfieldba1820d2015-04-13 17:39:12 -04001748 # If the callback throws an exception it should be raised here.
1749 self.assertRaises(
1750 TypeError, self._interactInMemory, server, client
1751 )
1752 self.assertEqual([(server,)], advertise_args)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001753
1754
Cory Benfieldba1820d2015-04-13 17:39:12 -04001755 def test_npn_advertise_error(self):
1756 """
1757 Test that we can handle exceptions in the advertise callback. If
1758 advertise fails no NPN is advertised to the client.
1759 """
1760 select_args = []
1761 def advertise(conn):
1762 raise TypeError
1763 def select(conn, options):
1764 select_args.append((conn, options))
1765 return b''
Cory Benfield0ea76e72015-03-22 09:05:28 +00001766
Cory Benfieldba1820d2015-04-13 17:39:12 -04001767 server_context = Context(TLSv1_METHOD)
1768 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001769
Cory Benfieldba1820d2015-04-13 17:39:12 -04001770 client_context = Context(TLSv1_METHOD)
1771 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001772
Cory Benfieldba1820d2015-04-13 17:39:12 -04001773 # Necessary to actually accept the connection
1774 server_context.use_privatekey(
1775 load_privatekey(FILETYPE_PEM, server_key_pem))
1776 server_context.use_certificate(
1777 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001778
Cory Benfieldba1820d2015-04-13 17:39:12 -04001779 # Do a little connection to trigger the logic
1780 server = Connection(server_context, None)
1781 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001782
Cory Benfieldba1820d2015-04-13 17:39:12 -04001783 client = Connection(client_context, None)
1784 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001785
Cory Benfieldba1820d2015-04-13 17:39:12 -04001786 # If the client doesn't return anything, the connection will fail.
1787 self.assertRaises(
1788 TypeError, self._interactInMemory, server, client
1789 )
1790 self.assertEqual([], select_args)
1791
1792 else:
1793 # No NPN.
1794 def test_npn_not_implemented(self):
1795 # Test the context methods first.
1796 context = Context(TLSv1_METHOD)
1797 fail_methods = [
1798 context.set_npn_advertise_callback,
1799 context.set_npn_select_callback,
1800 ]
1801 for method in fail_methods:
1802 self.assertRaises(
1803 NotImplementedError, method, None
1804 )
1805
1806 # Now test a connection.
1807 conn = Connection(context)
1808 fail_methods = [
1809 conn.get_next_proto_negotiated,
1810 ]
1811 for method in fail_methods:
1812 self.assertRaises(NotImplementedError, method)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001813
1814
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001815
Cory Benfield12eae892014-06-07 15:42:56 +01001816class ApplicationLayerProtoNegotiationTests(TestCase, _LoopbackMixin):
1817 """
1818 Tests for ALPN in PyOpenSSL.
1819 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001820 # Skip tests on versions that don't support ALPN.
1821 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001822
Cory Benfielde46fa842015-04-13 16:50:49 -04001823 def test_alpn_success(self):
1824 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001825 Clients and servers that agree on the negotiated ALPN protocol can
1826 correct establish a connection, and the agreed protocol is reported
1827 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001828 """
1829 select_args = []
1830 def select(conn, options):
1831 select_args.append((conn, options))
1832 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001833
Cory Benfielde46fa842015-04-13 16:50:49 -04001834 client_context = Context(TLSv1_METHOD)
1835 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001836
Cory Benfielde46fa842015-04-13 16:50:49 -04001837 server_context = Context(TLSv1_METHOD)
1838 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001839
Cory Benfielde46fa842015-04-13 16:50:49 -04001840 # Necessary to actually accept the connection
1841 server_context.use_privatekey(
1842 load_privatekey(FILETYPE_PEM, server_key_pem))
1843 server_context.use_certificate(
1844 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001845
Cory Benfielde46fa842015-04-13 16:50:49 -04001846 # Do a little connection to trigger the logic
1847 server = Connection(server_context, None)
1848 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001849
Cory Benfielde46fa842015-04-13 16:50:49 -04001850 client = Connection(client_context, None)
1851 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001852
Cory Benfielde46fa842015-04-13 16:50:49 -04001853 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001854
Cory Benfielde46fa842015-04-13 16:50:49 -04001855 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
1856
1857 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1858 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001859
1860
Cory Benfielde46fa842015-04-13 16:50:49 -04001861 def test_alpn_set_on_connection(self):
1862 """
1863 The same as test_alpn_success, but setting the ALPN protocols on
1864 the connection rather than the context.
1865 """
1866 select_args = []
1867 def select(conn, options):
1868 select_args.append((conn, options))
1869 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001870
Cory Benfielde46fa842015-04-13 16:50:49 -04001871 # Setup the client context but don't set any ALPN protocols.
1872 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001873
Cory Benfielde46fa842015-04-13 16:50:49 -04001874 server_context = Context(TLSv1_METHOD)
1875 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001876
Cory Benfielde46fa842015-04-13 16:50:49 -04001877 # Necessary to actually accept the connection
1878 server_context.use_privatekey(
1879 load_privatekey(FILETYPE_PEM, server_key_pem))
1880 server_context.use_certificate(
1881 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001882
Cory Benfielde46fa842015-04-13 16:50:49 -04001883 # Do a little connection to trigger the logic
1884 server = Connection(server_context, None)
1885 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001886
Cory Benfielde46fa842015-04-13 16:50:49 -04001887 # Set the ALPN protocols on the client connection.
1888 client = Connection(client_context, None)
1889 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1890 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001891
Cory Benfielde46fa842015-04-13 16:50:49 -04001892 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001893
Cory Benfielde46fa842015-04-13 16:50:49 -04001894 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001895
Cory Benfielde46fa842015-04-13 16:50:49 -04001896 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1897 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001898
1899
Cory Benfielde46fa842015-04-13 16:50:49 -04001900 def test_alpn_server_fail(self):
1901 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001902 When clients and servers cannot agree on what protocol to use next
1903 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001904 """
1905 select_args = []
1906 def select(conn, options):
1907 select_args.append((conn, options))
1908 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001909
Cory Benfielde46fa842015-04-13 16:50:49 -04001910 client_context = Context(TLSv1_METHOD)
1911 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001912
Cory Benfielde46fa842015-04-13 16:50:49 -04001913 server_context = Context(TLSv1_METHOD)
1914 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001915
Cory Benfielde46fa842015-04-13 16:50:49 -04001916 # Necessary to actually accept the connection
1917 server_context.use_privatekey(
1918 load_privatekey(FILETYPE_PEM, server_key_pem))
1919 server_context.use_certificate(
1920 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001921
Cory Benfielde46fa842015-04-13 16:50:49 -04001922 # Do a little connection to trigger the logic
1923 server = Connection(server_context, None)
1924 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001925
Cory Benfielde46fa842015-04-13 16:50:49 -04001926 client = Connection(client_context, None)
1927 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001928
Cory Benfielde46fa842015-04-13 16:50:49 -04001929 # If the client doesn't return anything, the connection will fail.
1930 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001931
Cory Benfielde46fa842015-04-13 16:50:49 -04001932 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001933
1934
Cory Benfielde46fa842015-04-13 16:50:49 -04001935 def test_alpn_no_server(self):
1936 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001937 When clients and servers cannot agree on what protocol to use next
1938 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04001939 """
1940 client_context = Context(TLSv1_METHOD)
1941 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04001942
Cory Benfielde46fa842015-04-13 16:50:49 -04001943 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04001944
Cory Benfielde46fa842015-04-13 16:50:49 -04001945 # Necessary to actually accept the connection
1946 server_context.use_privatekey(
1947 load_privatekey(FILETYPE_PEM, server_key_pem))
1948 server_context.use_certificate(
1949 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04001950
Cory Benfielde46fa842015-04-13 16:50:49 -04001951 # Do a little connection to trigger the logic
1952 server = Connection(server_context, None)
1953 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001954
Cory Benfielde46fa842015-04-13 16:50:49 -04001955 client = Connection(client_context, None)
1956 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001957
Cory Benfielde46fa842015-04-13 16:50:49 -04001958 # Do the dance.
1959 self._interactInMemory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04001960
Cory Benfielde46fa842015-04-13 16:50:49 -04001961 self.assertEqual(client.get_alpn_proto_negotiated(), b'')
Cory Benfielde3d57152015-04-11 17:57:35 -04001962
1963
Cory Benfielde46fa842015-04-13 16:50:49 -04001964 def test_alpn_callback_exception(self):
1965 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001966 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04001967 """
1968 select_args = []
1969 def select(conn, options):
1970 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04001971 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001972
Cory Benfielde46fa842015-04-13 16:50:49 -04001973 client_context = Context(TLSv1_METHOD)
1974 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04001975
Cory Benfielde46fa842015-04-13 16:50:49 -04001976 server_context = Context(TLSv1_METHOD)
1977 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04001978
Cory Benfielde46fa842015-04-13 16:50:49 -04001979 # Necessary to actually accept the connection
1980 server_context.use_privatekey(
1981 load_privatekey(FILETYPE_PEM, server_key_pem))
1982 server_context.use_certificate(
1983 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04001984
Cory Benfielde46fa842015-04-13 16:50:49 -04001985 # Do a little connection to trigger the logic
1986 server = Connection(server_context, None)
1987 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001988
Cory Benfielde46fa842015-04-13 16:50:49 -04001989 client = Connection(client_context, None)
1990 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001991
Cory Benfielde46fa842015-04-13 16:50:49 -04001992 self.assertRaises(
1993 TypeError, self._interactInMemory, server, client
1994 )
1995 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfieldf1177e72015-04-12 09:11:49 -04001996
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001997 else:
1998 # No ALPN.
1999 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04002000 """
2001 If ALPN is not in OpenSSL, we should raise NotImplementedError.
2002 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002003 # Test the context methods first.
2004 context = Context(TLSv1_METHOD)
Cory Benfield307e9e62015-04-13 18:21:12 -04002005 self.assertRaises(
2006 NotImplementedError, context.set_alpn_protos, None
2007 )
2008 self.assertRaises(
2009 NotImplementedError, context.set_alpn_select_callback, None
2010 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002011
2012 # Now test a connection.
2013 conn = Connection(context)
Cory Benfield307e9e62015-04-13 18:21:12 -04002014 self.assertRaises(
Alex Gaynor68417232015-09-04 07:56:29 -04002015 NotImplementedError, conn.set_alpn_protos, None
Cory Benfield307e9e62015-04-13 18:21:12 -04002016 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002017
Cory Benfieldf1177e72015-04-12 09:11:49 -04002018
Cory Benfield12eae892014-06-07 15:42:56 +01002019
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002020class SessionTests(TestCase):
2021 """
2022 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
2023 """
2024 def test_construction(self):
2025 """
2026 :py:class:`Session` can be constructed with no arguments, creating a new
2027 instance of that type.
2028 """
2029 new_session = Session()
2030 self.assertTrue(isinstance(new_session, Session))
2031
2032
2033 def test_construction_wrong_args(self):
2034 """
2035 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
2036 is raised.
2037 """
2038 self.assertRaises(TypeError, Session, 123)
2039 self.assertRaises(TypeError, Session, "hello")
2040 self.assertRaises(TypeError, Session, object())
2041
2042
2043
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002044class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05002045 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002046 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002047 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002048 # XXX get_peer_certificate -> None
2049 # XXX sock_shutdown
2050 # XXX master_key -> TypeError
2051 # XXX server_random -> TypeError
2052 # XXX state_string
2053 # XXX connect -> TypeError
2054 # XXX connect_ex -> TypeError
2055 # XXX set_connect_state -> TypeError
2056 # XXX set_accept_state -> TypeError
2057 # XXX renegotiate_pending
2058 # XXX do_handshake -> TypeError
2059 # XXX bio_read -> TypeError
2060 # XXX recv -> TypeError
2061 # XXX send -> TypeError
2062 # XXX bio_write -> TypeError
2063
Rick Deane15b1472009-07-09 15:53:42 -05002064 def test_type(self):
2065 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002066 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002067 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002068 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002069 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05002070 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002071 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002072
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002073
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002074 def test_get_context(self):
2075 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002076 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
2077 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002078 """
2079 context = Context(TLSv1_METHOD)
2080 connection = Connection(context, None)
2081 self.assertIdentical(connection.get_context(), context)
2082
2083
2084 def test_get_context_wrong_args(self):
2085 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002086 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002087 arguments.
2088 """
2089 connection = Connection(Context(TLSv1_METHOD), None)
2090 self.assertRaises(TypeError, connection.get_context, None)
2091
2092
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002093 def test_set_context_wrong_args(self):
2094 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002095 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
2096 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002097 than 1.
2098 """
2099 ctx = Context(TLSv1_METHOD)
2100 connection = Connection(ctx, None)
2101 self.assertRaises(TypeError, connection.set_context)
2102 self.assertRaises(TypeError, connection.set_context, object())
2103 self.assertRaises(TypeError, connection.set_context, "hello")
2104 self.assertRaises(TypeError, connection.set_context, 1)
2105 self.assertRaises(TypeError, connection.set_context, 1, 2)
2106 self.assertRaises(
2107 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
2108 self.assertIdentical(ctx, connection.get_context())
2109
2110
2111 def test_set_context(self):
2112 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002113 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002114 for the connection.
2115 """
2116 original = Context(SSLv23_METHOD)
2117 replacement = Context(TLSv1_METHOD)
2118 connection = Connection(original, None)
2119 connection.set_context(replacement)
2120 self.assertIdentical(replacement, connection.get_context())
2121 # Lose our references to the contexts, just in case the Connection isn't
2122 # properly managing its own contributions to their reference counts.
2123 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002124 collect()
2125
2126
2127 def test_set_tlsext_host_name_wrong_args(self):
2128 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002129 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002130 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09002131 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002132 """
2133 conn = Connection(Context(TLSv1_METHOD), None)
2134 self.assertRaises(TypeError, conn.set_tlsext_host_name)
2135 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
2136 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
2137 self.assertRaises(
2138 TypeError, conn.set_tlsext_host_name, b("with\0null"))
2139
Abraham Martinc5484ba2015-03-25 15:33:05 +00002140 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002141 # On Python 3.x, don't accidentally implicitly convert from text.
2142 self.assertRaises(
2143 TypeError,
2144 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002145
2146
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002147 def test_get_servername_wrong_args(self):
2148 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002149 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002150 arguments.
2151 """
2152 connection = Connection(Context(TLSv1_METHOD), None)
2153 self.assertRaises(TypeError, connection.get_servername, object())
2154 self.assertRaises(TypeError, connection.get_servername, 1)
2155 self.assertRaises(TypeError, connection.get_servername, "hello")
2156
2157
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002158 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002159 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002160 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002161 immediate read.
2162 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002163 connection = Connection(Context(TLSv1_METHOD), None)
2164 self.assertEquals(connection.pending(), 0)
2165
2166
2167 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002168 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002169 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002170 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002171 connection = Connection(Context(TLSv1_METHOD), None)
2172 self.assertRaises(TypeError, connection.pending, None)
2173
2174
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002175 def test_peek(self):
2176 """
2177 :py:obj:`Connection.recv` peeks into the connection if :py:obj:`socket.MSG_PEEK` is passed.
2178 """
2179 server, client = self._loopback()
2180 server.send(b('xy'))
2181 self.assertEqual(client.recv(2, MSG_PEEK), b('xy'))
2182 self.assertEqual(client.recv(2, MSG_PEEK), b('xy'))
2183 self.assertEqual(client.recv(2), b('xy'))
2184
2185
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002186 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002187 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002188 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002189 argument or with the wrong number of arguments.
2190 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002191 connection = Connection(Context(TLSv1_METHOD), socket())
2192 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002193 self.assertRaises(TypeError, connection.connect)
2194 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002195
kjavfe508d62015-09-02 12:20:35 +01002196 def test_connection_undefined_attr(self):
2197 """
2198 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
2199 argument or with the wrong number of arguments.
2200 """
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002201
kjavfe508d62015-09-02 12:20:35 +01002202 def attr_access_test(connection):
2203 return connection.an_attribute_which_is_not_defined
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002204
kjavfe508d62015-09-02 12:20:35 +01002205 connection = Connection(Context(TLSv1_METHOD), None)
2206 self.assertRaises(AttributeError, attr_access_test, connection)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002207
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002208 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002209 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002210 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002211 connect method raises it.
2212 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002213 client = socket()
2214 context = Context(TLSv1_METHOD)
2215 clientSSL = Connection(context, client)
Alex Gaynorfed8e432015-09-05 14:12:22 -04002216 # pytest.raises here doesn't work because of a bug in py.test:
2217 # https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002218 try:
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002219 clientSSL.connect(("127.0.0.1", 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002220 except error as e:
2221 pass
2222 assert e.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002223
2224 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002225 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002226 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002227 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002228 port = socket()
2229 port.bind(('', 0))
2230 port.listen(3)
2231
2232 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002233 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2234 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002235
2236
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002237 if platform == "darwin":
2238 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2239 else:
2240 def test_connect_ex(self):
2241 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002242 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002243 errno instead of raising an exception.
2244 """
2245 port = socket()
2246 port.bind(('', 0))
2247 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002248
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002249 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2250 clientSSL.setblocking(False)
2251 result = clientSSL.connect_ex(port.getsockname())
2252 expected = (EINPROGRESS, EWOULDBLOCK)
2253 self.assertTrue(
2254 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002255
2256
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002257 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002258 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002259 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002260 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002261 connection = Connection(Context(TLSv1_METHOD), socket())
2262 self.assertRaises(TypeError, connection.accept, None)
2263
2264
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002265 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002266 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002267 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
2268 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002269 connection originated from.
2270 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002271 ctx = Context(TLSv1_METHOD)
2272 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2273 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002274 port = socket()
2275 portSSL = Connection(ctx, port)
2276 portSSL.bind(('', 0))
2277 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002278
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002279 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002280
2281 # Calling portSSL.getsockname() here to get the server IP address sounds
2282 # great, but frequently fails on Windows.
2283 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002284
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002285 serverSSL, address = portSSL.accept()
2286
2287 self.assertTrue(isinstance(serverSSL, Connection))
2288 self.assertIdentical(serverSSL.get_context(), ctx)
2289 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002290
2291
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002292 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002293 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002294 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002295 number of arguments or with arguments other than integers.
2296 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002297 connection = Connection(Context(TLSv1_METHOD), None)
2298 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04002299 self.assertRaises(TypeError, connection.get_shutdown, None)
2300 self.assertRaises(TypeError, connection.set_shutdown)
2301 self.assertRaises(TypeError, connection.set_shutdown, None)
2302 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002303
2304
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002305 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002306 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002307 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002308 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002309 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002310 self.assertFalse(server.shutdown())
2311 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002312 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002313 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
2314 client.shutdown()
Alex Gaynor43307782015-09-04 09:05:45 -04002315 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002316 self.assertRaises(ZeroReturnError, server.recv, 1024)
Alex Gaynor43307782015-09-04 09:05:45 -04002317 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002318
2319
Paul Aurichc85e0862015-01-08 08:34:33 -08002320 def test_shutdown_closed(self):
2321 """
2322 If the underlying socket is closed, :py:obj:`Connection.shutdown` propagates the
2323 write error from the low level write call.
2324 """
2325 server, client = self._loopback()
2326 server.sock_shutdown(2)
2327 exc = self.assertRaises(SysCallError, server.shutdown)
2328 if platform == "win32":
2329 self.assertEqual(exc.args[0], ESHUTDOWN)
2330 else:
2331 self.assertEqual(exc.args[0], EPIPE)
2332
2333
Glyph89389472015-04-14 17:29:26 -04002334 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002335 """
Glyph89389472015-04-14 17:29:26 -04002336 If the underlying connection is truncated, :obj:`Connection.shutdown`
2337 raises an :obj:`Error`.
Glyph6064ec32015-04-14 16:38:22 -04002338 """
Glyph89389472015-04-14 17:29:26 -04002339 server_ctx = Context(TLSv1_METHOD)
2340 client_ctx = Context(TLSv1_METHOD)
2341 server_ctx.use_privatekey(
2342 load_privatekey(FILETYPE_PEM, server_key_pem))
2343 server_ctx.use_certificate(
2344 load_certificate(FILETYPE_PEM, server_cert_pem))
2345 server = Connection(server_ctx, None)
2346 client = Connection(client_ctx, None)
2347 self._handshakeInMemory(client, server)
2348 self.assertEqual(server.shutdown(), False)
2349 self.assertRaises(WantReadError, server.shutdown)
2350 server.bio_shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002351 self.assertRaises(Error, server.shutdown)
2352
2353
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002354 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002355 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002356 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002357 process.
2358 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002359 connection = Connection(Context(TLSv1_METHOD), socket())
2360 connection.set_shutdown(RECEIVED_SHUTDOWN)
2361 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2362
2363
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002364 if not PY3:
2365 def test_set_shutdown_long(self):
2366 """
2367 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
2368 of type :py:obj:`long` as well as :py:obj:`int`.
2369 """
2370 connection = Connection(Context(TLSv1_METHOD), socket())
2371 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
2372 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2373
2374
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002375 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002376 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002377 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
2378 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002379 with any arguments.
2380 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002381 conn = Connection(Context(TLSv1_METHOD), None)
2382 self.assertRaises(TypeError, conn.get_app_data, None)
2383 self.assertRaises(TypeError, conn.set_app_data)
2384 self.assertRaises(TypeError, conn.set_app_data, None, None)
2385
2386
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002387 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002388 """
2389 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002390 :py:obj:`Connection.set_app_data` and later retrieved with
2391 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002392 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002393 conn = Connection(Context(TLSv1_METHOD), None)
2394 app_data = object()
2395 conn.set_app_data(app_data)
2396 self.assertIdentical(conn.get_app_data(), app_data)
2397
2398
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002399 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002400 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002401 :py:obj:`Connection.makefile` is not implemented and calling that method raises
2402 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002403 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002404 conn = Connection(Context(TLSv1_METHOD), None)
2405 self.assertRaises(NotImplementedError, conn.makefile)
2406
2407
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002408 def test_get_peer_cert_chain_wrong_args(self):
2409 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002410 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002411 arguments.
2412 """
2413 conn = Connection(Context(TLSv1_METHOD), None)
2414 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
2415 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
2416 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
2417 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
2418
2419
2420 def test_get_peer_cert_chain(self):
2421 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002422 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002423 the connected server returned for the certification verification.
2424 """
2425 chain = _create_certificate_chain()
2426 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2427
2428 serverContext = Context(TLSv1_METHOD)
2429 serverContext.use_privatekey(skey)
2430 serverContext.use_certificate(scert)
2431 serverContext.add_extra_chain_cert(icert)
2432 serverContext.add_extra_chain_cert(cacert)
2433 server = Connection(serverContext, None)
2434 server.set_accept_state()
2435
2436 # Create the client
2437 clientContext = Context(TLSv1_METHOD)
2438 clientContext.set_verify(VERIFY_NONE, verify_cb)
2439 client = Connection(clientContext, None)
2440 client.set_connect_state()
2441
2442 self._interactInMemory(client, server)
2443
2444 chain = client.get_peer_cert_chain()
2445 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002446 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002447 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002448 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002449 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002450 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002451 "Authority Certificate", chain[2].get_subject().CN)
2452
2453
2454 def test_get_peer_cert_chain_none(self):
2455 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002456 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002457 certificate chain.
2458 """
2459 ctx = Context(TLSv1_METHOD)
2460 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2461 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2462 server = Connection(ctx, None)
2463 server.set_accept_state()
2464 client = Connection(Context(TLSv1_METHOD), None)
2465 client.set_connect_state()
2466 self._interactInMemory(client, server)
2467 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002468
2469
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002470 def test_get_session_wrong_args(self):
2471 """
2472 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
2473 with any arguments.
2474 """
2475 ctx = Context(TLSv1_METHOD)
2476 server = Connection(ctx, None)
2477 self.assertRaises(TypeError, server.get_session, 123)
2478 self.assertRaises(TypeError, server.get_session, "hello")
2479 self.assertRaises(TypeError, server.get_session, object())
2480
2481
2482 def test_get_session_unconnected(self):
2483 """
2484 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
2485 an object which has not been connected.
2486 """
2487 ctx = Context(TLSv1_METHOD)
2488 server = Connection(ctx, None)
2489 session = server.get_session()
2490 self.assertIdentical(None, session)
2491
2492
2493 def test_server_get_session(self):
2494 """
2495 On the server side of a connection, :py:obj:`Connection.get_session`
2496 returns a :py:class:`Session` instance representing the SSL session for
2497 that connection.
2498 """
2499 server, client = self._loopback()
2500 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002501 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002502
2503
2504 def test_client_get_session(self):
2505 """
2506 On the client side of a connection, :py:obj:`Connection.get_session`
2507 returns a :py:class:`Session` instance representing the SSL session for
2508 that connection.
2509 """
2510 server, client = self._loopback()
2511 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002512 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002513
2514
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002515 def test_set_session_wrong_args(self):
2516 """
2517 If called with an object that is not an instance of :py:class:`Session`,
2518 or with other than one argument, :py:obj:`Connection.set_session` raises
2519 :py:obj:`TypeError`.
2520 """
2521 ctx = Context(TLSv1_METHOD)
2522 connection = Connection(ctx, None)
2523 self.assertRaises(TypeError, connection.set_session)
2524 self.assertRaises(TypeError, connection.set_session, 123)
2525 self.assertRaises(TypeError, connection.set_session, "hello")
2526 self.assertRaises(TypeError, connection.set_session, object())
2527 self.assertRaises(
2528 TypeError, connection.set_session, Session(), Session())
2529
2530
2531 def test_client_set_session(self):
2532 """
2533 :py:obj:`Connection.set_session`, when used prior to a connection being
2534 established, accepts a :py:class:`Session` instance and causes an
2535 attempt to re-use the session it represents when the SSL handshake is
2536 performed.
2537 """
2538 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2539 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2540 ctx = Context(TLSv1_METHOD)
2541 ctx.use_privatekey(key)
2542 ctx.use_certificate(cert)
2543 ctx.set_session_id("unity-test")
2544
2545 def makeServer(socket):
2546 server = Connection(ctx, socket)
2547 server.set_accept_state()
2548 return server
2549
2550 originalServer, originalClient = self._loopback(
2551 serverFactory=makeServer)
2552 originalSession = originalClient.get_session()
2553
2554 def makeClient(socket):
2555 client = self._loopbackClientFactory(socket)
2556 client.set_session(originalSession)
2557 return client
2558 resumedServer, resumedClient = self._loopback(
2559 serverFactory=makeServer,
2560 clientFactory=makeClient)
2561
2562 # This is a proxy: in general, we have no access to any unique
2563 # identifier for the session (new enough versions of OpenSSL expose a
2564 # hash which could be usable, but "new enough" is very, very new).
2565 # Instead, exploit the fact that the master key is re-used if the
2566 # session is re-used. As long as the master key for the two connections
2567 # is the same, the session was re-used!
2568 self.assertEqual(
2569 originalServer.master_key(), resumedServer.master_key())
2570
2571
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002572 def test_set_session_wrong_method(self):
2573 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002574 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
2575 instance associated with a context using a different SSL method than the
2576 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
2577 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002578 """
2579 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2580 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2581 ctx = Context(TLSv1_METHOD)
2582 ctx.use_privatekey(key)
2583 ctx.use_certificate(cert)
2584 ctx.set_session_id("unity-test")
2585
2586 def makeServer(socket):
2587 server = Connection(ctx, socket)
2588 server.set_accept_state()
2589 return server
2590
2591 originalServer, originalClient = self._loopback(
2592 serverFactory=makeServer)
2593 originalSession = originalClient.get_session()
2594
2595 def makeClient(socket):
2596 # Intentionally use a different, incompatible method here.
2597 client = Connection(Context(SSLv3_METHOD), socket)
2598 client.set_connect_state()
2599 client.set_session(originalSession)
2600 return client
2601
2602 self.assertRaises(
2603 Error,
2604 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2605
2606
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002607 def test_wantWriteError(self):
2608 """
2609 :py:obj:`Connection` methods which generate output raise
2610 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2611 fail indicating a should-write state.
2612 """
2613 client_socket, server_socket = socket_pair()
2614 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002615 # anything. Only write a single byte at a time so we can be sure we
2616 # completely fill the buffer. Even though the socket API is allowed to
2617 # signal a short write via its return value it seems this doesn't
2618 # always happen on all platforms (FreeBSD and OS X particular) for the
2619 # very last bit of available buffer space.
2620 msg = b"x"
2621 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002622 try:
2623 client_socket.send(msg)
2624 except error as e:
2625 if e.errno == EWOULDBLOCK:
2626 break
2627 raise
2628 else:
2629 self.fail(
2630 "Failed to fill socket buffer, cannot test BIO want write")
2631
2632 ctx = Context(TLSv1_METHOD)
2633 conn = Connection(ctx, client_socket)
2634 # Client's speak first, so make it an SSL client
2635 conn.set_connect_state()
2636 self.assertRaises(WantWriteError, conn.do_handshake)
2637
2638 # XXX want_read
2639
Fedor Brunner416f4a12014-03-28 13:18:38 +01002640 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002641 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002642 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2643 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002644 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002645 ctx = Context(TLSv1_METHOD)
2646 connection = Connection(ctx, None)
2647 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002648
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002649
Fedor Brunner416f4a12014-03-28 13:18:38 +01002650 def test_get_peer_finished_before_connect(self):
2651 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002652 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2653 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002654 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002655 ctx = Context(TLSv1_METHOD)
2656 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002657 self.assertEqual(connection.get_peer_finished(), None)
2658
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002659
Fedor Brunner416f4a12014-03-28 13:18:38 +01002660 def test_get_finished(self):
2661 """
2662 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002663 message send from client, or server. Finished messages are send during
2664 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002665 """
2666
Fedor Brunner5747b932014-03-05 14:22:34 +01002667 server, client = self._loopback()
2668
2669 self.assertNotEqual(server.get_finished(), None)
2670 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002671
Jean-Paul Calderoned979f232014-03-30 11:58:00 -04002672
Fedor Brunner416f4a12014-03-28 13:18:38 +01002673 def test_get_peer_finished(self):
2674 """
2675 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002676 message received from client, or server. Finished messages are send
2677 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002678 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002679 server, client = self._loopback()
2680
2681 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002682 self.assertTrue(len(server.get_peer_finished()) > 0)
2683
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002684
Fedor Brunner416f4a12014-03-28 13:18:38 +01002685 def test_tls_finished_message_symmetry(self):
2686 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002687 The TLS Finished message send by server must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002688 received by client.
2689
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002690 The TLS Finished message send by client must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002691 received by server.
2692 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002693 server, client = self._loopback()
2694
Fedor Brunner5747b932014-03-05 14:22:34 +01002695 self.assertEqual(server.get_finished(), client.get_peer_finished())
2696 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002697
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002698
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002699 def test_get_cipher_name_before_connect(self):
2700 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002701 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2702 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002703 """
2704 ctx = Context(TLSv1_METHOD)
2705 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002706 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002707
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002708
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002709 def test_get_cipher_name(self):
2710 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002711 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2712 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002713 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002714 server, client = self._loopback()
2715 server_cipher_name, client_cipher_name = \
2716 server.get_cipher_name(), client.get_cipher_name()
2717
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002718 self.assertIsInstance(server_cipher_name, text_type)
2719 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002720
2721 self.assertEqual(server_cipher_name, client_cipher_name)
2722
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002723
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002724 def test_get_cipher_version_before_connect(self):
2725 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002726 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2727 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002728 """
2729 ctx = Context(TLSv1_METHOD)
2730 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002731 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002732
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002733
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002734 def test_get_cipher_version(self):
2735 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002736 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2737 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002738 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002739 server, client = self._loopback()
2740 server_cipher_version, client_cipher_version = \
2741 server.get_cipher_version(), client.get_cipher_version()
2742
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002743 self.assertIsInstance(server_cipher_version, text_type)
2744 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002745
2746 self.assertEqual(server_cipher_version, client_cipher_version)
2747
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002748
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002749 def test_get_cipher_bits_before_connect(self):
2750 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002751 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2752 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002753 """
2754 ctx = Context(TLSv1_METHOD)
2755 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002756 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002757
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002758
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002759 def test_get_cipher_bits(self):
2760 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002761 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2762 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002763 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002764 server, client = self._loopback()
2765 server_cipher_bits, client_cipher_bits = \
2766 server.get_cipher_bits(), client.get_cipher_bits()
2767
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002768 self.assertIsInstance(server_cipher_bits, int)
2769 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002770
2771 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002772
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002773
Jim Shaverabff1882015-05-27 09:15:55 -04002774 def test_get_protocol_version_name(self):
2775 """
2776 :py:obj:`Connection.get_protocol_version_name()` returns a string
2777 giving the protocol version of the current connection.
2778 """
2779 server, client = self._loopback()
2780 client_protocol_version_name = client.get_protocol_version_name()
2781 server_protocol_version_name = server.get_protocol_version_name()
2782
Jim Shaver58d25732015-05-28 11:52:32 -04002783 self.assertIsInstance(server_protocol_version_name, text_type)
2784 self.assertIsInstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002785
2786 self.assertEqual(server_protocol_version_name, client_protocol_version_name)
2787
2788
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002789 def test_get_protocol_version(self):
2790 """
Alex Gaynor43307782015-09-04 09:05:45 -04002791 :py:obj:`Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002792 giving the protocol version of the current connection.
2793 """
2794 server, client = self._loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002795 client_protocol_version = client.get_protocol_version()
2796 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002797
Jim Shaverabff1882015-05-27 09:15:55 -04002798 self.assertIsInstance(server_protocol_version, int)
2799 self.assertIsInstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002800
2801 self.assertEqual(server_protocol_version, client_protocol_version)
2802
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002803
Jim Shaver208438c2015-05-28 09:52:38 -04002804
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002805class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002806 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002807 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002808 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002809 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002810 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002811 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002812 arguments.
2813 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002814 connection = Connection(Context(TLSv1_METHOD), None)
2815 self.assertRaises(TypeError, connection.get_cipher_list, None)
2816
2817
2818 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002819 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002820 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2821 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002822 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002823 connection = Connection(Context(TLSv1_METHOD), None)
2824 ciphers = connection.get_cipher_list()
2825 self.assertTrue(isinstance(ciphers, list))
2826 for cipher in ciphers:
2827 self.assertTrue(isinstance(cipher, str))
2828
2829
2830
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002831class ConnectionSendTests(TestCase, _LoopbackMixin):
2832 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002833 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002834 """
2835 def test_wrong_args(self):
2836 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002837 When called with arguments other than string argument for its first
2838 parameter or more than two arguments, :py:obj:`Connection.send` raises
2839 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002840 """
2841 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002842 self.assertRaises(TypeError, connection.send)
2843 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002844 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002845
2846
2847 def test_short_bytes(self):
2848 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002849 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002850 and returns the number of bytes sent.
2851 """
2852 server, client = self._loopback()
2853 count = server.send(b('xy'))
2854 self.assertEquals(count, 2)
2855 self.assertEquals(client.recv(2), b('xy'))
2856
Abraham Martinef063482015-03-25 14:06:24 +00002857
2858 def test_text(self):
2859 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002860 When passed a text, :py:obj:`Connection.send` transmits all of it and
2861 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002862 """
2863 server, client = self._loopback()
2864 with catch_warnings(record=True) as w:
2865 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002866 count = server.send(b"xy".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002867 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002868 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002869 WARNING_TYPE_EXPECTED
2870 ),
2871 str(w[-1].message)
2872 )
2873 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinef063482015-03-25 14:06:24 +00002874 self.assertEquals(count, 2)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002875 self.assertEquals(client.recv(2), b"xy")
Abraham Martinef063482015-03-25 14:06:24 +00002876
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002877 try:
2878 memoryview
2879 except NameError:
2880 "cannot test sending memoryview without memoryview"
2881 else:
2882 def test_short_memoryview(self):
2883 """
2884 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002885 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002886 bytes sent.
2887 """
2888 server, client = self._loopback()
2889 count = server.send(memoryview(b('xy')))
2890 self.assertEquals(count, 2)
2891 self.assertEquals(client.recv(2), b('xy'))
2892
2893
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002894 try:
2895 buffer
2896 except NameError:
2897 "cannot test sending buffer without buffer"
2898 else:
2899 def test_short_buffer(self):
2900 """
2901 When passed a buffer containing a small number of bytes,
2902 :py:obj:`Connection.send` transmits all of them and returns the number of
2903 bytes sent.
2904 """
2905 server, client = self._loopback()
2906 count = server.send(buffer(b('xy')))
2907 self.assertEquals(count, 2)
2908 self.assertEquals(client.recv(2), b('xy'))
2909
2910
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002911
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002912def _make_memoryview(size):
2913 """
2914 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2915 size.
2916 """
2917 return memoryview(bytearray(size))
2918
2919
2920
Cory Benfield62d10332014-06-15 10:03:41 +01002921class ConnectionRecvIntoTests(TestCase, _LoopbackMixin):
2922 """
2923 Tests for :py:obj:`Connection.recv_into`
2924 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002925 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002926 """
2927 Assert that when the given buffer is passed to
2928 ``Connection.recv_into``, whatever bytes are available to be received
2929 that fit into that buffer are written into that buffer.
2930 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002931 output_buffer = factory(5)
2932
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002933 server, client = self._loopback()
2934 server.send(b('xy'))
2935
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002936 self.assertEqual(client.recv_into(output_buffer), 2)
2937 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002938
2939
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002940 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002941 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002942 :py:obj:`Connection.recv_into` can be passed a ``bytearray`` instance
2943 and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002944 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002945 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002946
2947
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002948 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002949 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002950 Assert that when the given buffer is passed to ``Connection.recv_into``
2951 along with a value for ``nbytes`` that is less than the size of that
2952 buffer, only ``nbytes`` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002953 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002954 output_buffer = factory(10)
2955
Cory Benfield62d10332014-06-15 10:03:41 +01002956 server, client = self._loopback()
2957 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002958
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002959 self.assertEqual(client.recv_into(output_buffer, 5), 5)
2960 self.assertEqual(
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002961 output_buffer, bytearray(b('abcde\x00\x00\x00\x00\x00'))
2962 )
2963
2964
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002965 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002966 """
2967 When called with a ``bytearray`` instance,
2968 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter and
2969 doesn't copy in more than that number of bytes.
2970 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002971 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002972
2973
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002974 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002975 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002976 Assert that if there are more bytes available to be read from the
2977 receive buffer than would fit into the buffer passed to
2978 :py:obj:`Connection.recv_into`, only as many as fit are written into
2979 it.
Cory Benfield62d10332014-06-15 10:03:41 +01002980 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002981 output_buffer = factory(5)
2982
Cory Benfield62d10332014-06-15 10:03:41 +01002983 server, client = self._loopback()
2984 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002985
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002986 self.assertEqual(client.recv_into(output_buffer), 5)
2987 self.assertEqual(output_buffer, bytearray(b('abcde')))
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002988 rest = client.recv(5)
2989 self.assertEqual(b('fghij'), rest)
2990
2991
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002992 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002993 """
2994 When called with a ``bytearray`` instance,
2995 :py:obj:`Connection.recv_into` respects the size of the array and
2996 doesn't write more bytes into it than will fit.
2997 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002998 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002999
3000
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003001 def _really_doesnt_overfill_test(self, factory):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003002 """
3003 Assert that if the value given by ``nbytes`` is greater than the actual
3004 size of the output buffer passed to :py:obj:`Connection.recv_into`, the
3005 behavior is as if no value was given for ``nbytes`` at all.
3006 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003007 output_buffer = factory(5)
3008
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003009 server, client = self._loopback()
3010 server.send(b('abcdefghij'))
3011
3012 self.assertEqual(client.recv_into(output_buffer, 50), 5)
3013 self.assertEqual(output_buffer, bytearray(b('abcde')))
3014 rest = client.recv(5)
3015 self.assertEqual(b('fghij'), rest)
3016
3017
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003018 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003019 """
3020 When called with a ``bytearray`` instance and an ``nbytes`` value that
3021 is too large, :py:obj:`Connection.recv_into` respects the size of the
3022 array and not the ``nbytes`` value and doesn't write more bytes into
3023 the buffer than will fit.
3024 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003025 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003026
3027
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003028 def test_peek(self):
3029
3030 server, client = self._loopback()
3031 server.send(b('xy'))
3032
3033 for _ in range(2):
3034 output_buffer = bytearray(5)
3035 self.assertEqual(client.recv_into(output_buffer, flags=MSG_PEEK), 2)
3036 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
3037
3038
Cory Benfield62d10332014-06-15 10:03:41 +01003039 try:
3040 memoryview
3041 except NameError:
3042 "cannot test recv_into memoryview without memoryview"
3043 else:
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04003044 def test_memoryview_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01003045 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04003046 :py:obj:`Connection.recv_into` can be passed a ``memoryview``
3047 instance and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01003048 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003049 self._no_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003050
3051
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003052 def test_memoryview_respects_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01003053 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003054 When called with a ``memoryview`` instance,
3055 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter
3056 and doesn't copy more than that number of bytes in.
Cory Benfield62d10332014-06-15 10:03:41 +01003057 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003058 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003059
3060
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003061 def test_memoryview_doesnt_overfill(self):
Cory Benfield62d10332014-06-15 10:03:41 +01003062 """
Jean-Paul Calderone8fd82552015-03-15 17:21:07 -04003063 When called with a ``memoryview`` instance,
3064 :py:obj:`Connection.recv_into` respects the size of the array and
3065 doesn't write more bytes into it than will fit.
Cory Benfield62d10332014-06-15 10:03:41 +01003066 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003067 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003068
3069
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003070 def test_memoryview_really_doesnt_overfill(self):
3071 """
3072 When called with a ``memoryview`` instance and an ``nbytes`` value
3073 that is too large, :py:obj:`Connection.recv_into` respects the size
3074 of the array and not the ``nbytes`` value and doesn't write more
3075 bytes into the buffer than will fit.
3076 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003077 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003078
3079
Cory Benfield62d10332014-06-15 10:03:41 +01003080
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003081class ConnectionSendallTests(TestCase, _LoopbackMixin):
3082 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003083 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003084 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003085 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003086 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003087 When called with arguments other than a string argument for its first
3088 parameter or with more than two arguments, :py:obj:`Connection.sendall`
3089 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003090 """
3091 connection = Connection(Context(TLSv1_METHOD), None)
3092 self.assertRaises(TypeError, connection.sendall)
3093 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003094 self.assertRaises(
3095 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003096
3097
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003098 def test_short(self):
3099 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003100 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003101 it.
3102 """
3103 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04003104 server.sendall(b('x'))
3105 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003106
3107
Abraham Martinef063482015-03-25 14:06:24 +00003108 def test_text(self):
3109 """
Jean-Paul Calderone93477422015-04-13 20:38:57 -04003110 :py:obj:`Connection.sendall` transmits all the content in the string
3111 passed to it raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003112 """
3113 server, client = self._loopback()
3114 with catch_warnings(record=True) as w:
3115 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003116 server.sendall(b"x".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003117 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003118 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003119 WARNING_TYPE_EXPECTED
3120 ),
3121 str(w[-1].message)
3122 )
3123 self.assertIs(w[-1].category, DeprecationWarning)
3124 self.assertEquals(client.recv(1), b"x")
Abraham Martinef063482015-03-25 14:06:24 +00003125
3126
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003127 try:
3128 memoryview
3129 except NameError:
3130 "cannot test sending memoryview without memoryview"
3131 else:
3132 def test_short_memoryview(self):
3133 """
3134 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003135 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003136 """
3137 server, client = self._loopback()
3138 server.sendall(memoryview(b('x')))
3139 self.assertEquals(client.recv(1), b('x'))
3140
3141
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003142 try:
3143 buffer
3144 except NameError:
3145 "cannot test sending buffers without buffers"
3146 else:
3147 def test_short_buffers(self):
3148 """
3149 When passed a buffer containing a small number of bytes,
3150 :py:obj:`Connection.sendall` transmits all of them.
3151 """
3152 server, client = self._loopback()
3153 server.sendall(buffer(b('x')))
3154 self.assertEquals(client.recv(1), b('x'))
3155
3156
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003157 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003158 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003159 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003160 it even if this requires multiple calls of an underlying write function.
3161 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003162 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003163 # Should be enough, underlying SSL_write should only do 16k at a time.
3164 # On Windows, after 32k of bytes the write will block (forever - because
3165 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04003166 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003167 server.sendall(message)
3168 accum = []
3169 received = 0
3170 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003171 data = client.recv(1024)
3172 accum.append(data)
3173 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04003174 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003175
3176
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003177 def test_closed(self):
3178 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003179 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003180 write error from the low level write call.
3181 """
3182 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003183 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003184 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003185 if platform == "win32":
3186 self.assertEqual(exc.args[0], ESHUTDOWN)
3187 else:
3188 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003189
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003190
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04003191
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003192class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
3193 """
3194 Tests for SSL renegotiation APIs.
3195 """
3196 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003197 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003198 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003199 arguments.
3200 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003201 connection = Connection(Context(TLSv1_METHOD), None)
3202 self.assertRaises(TypeError, connection.renegotiate, None)
3203
3204
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003205 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003206 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003207 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003208 any arguments.
3209 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003210 connection = Connection(Context(TLSv1_METHOD), None)
3211 self.assertRaises(TypeError, connection.total_renegotiations, None)
3212
3213
3214 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003215 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003216 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003217 renegotiations have happened.
3218 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003219 connection = Connection(Context(TLSv1_METHOD), None)
3220 self.assertEquals(connection.total_renegotiations(), 0)
3221
3222
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003223# def test_renegotiate(self):
3224# """
3225# """
3226# server, client = self._loopback()
3227
3228# server.send("hello world")
3229# self.assertEquals(client.recv(len("hello world")), "hello world")
3230
3231# self.assertEquals(server.total_renegotiations(), 0)
3232# self.assertTrue(server.renegotiate())
3233
3234# server.setblocking(False)
3235# client.setblocking(False)
3236# while server.renegotiate_pending():
3237# client.do_handshake()
3238# server.do_handshake()
3239
3240# self.assertEquals(server.total_renegotiations(), 1)
3241
3242
3243
3244
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003245class ErrorTests(TestCase):
3246 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003247 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003248 """
3249 def test_type(self):
3250 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003251 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003252 """
3253 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05003254 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05003255
3256
3257
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003258class ConstantsTests(TestCase):
3259 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003260 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003261
3262 These are values defined by OpenSSL intended only to be used as flags to
3263 OpenSSL APIs. The only assertions it seems can be made about them is
3264 their values.
3265 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003266 # unittest.TestCase has no skip mechanism
3267 if OP_NO_QUERY_MTU is not None:
3268 def test_op_no_query_mtu(self):
3269 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003270 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003271 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003272 """
3273 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
3274 else:
3275 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003276
3277
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003278 if OP_COOKIE_EXCHANGE is not None:
3279 def test_op_cookie_exchange(self):
3280 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003281 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003282 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003283 """
3284 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
3285 else:
3286 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003287
3288
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003289 if OP_NO_TICKET is not None:
3290 def test_op_no_ticket(self):
3291 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003292 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003293 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003294 """
3295 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04003296 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003297 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05003298
3299
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003300 if OP_NO_COMPRESSION is not None:
3301 def test_op_no_compression(self):
3302 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003303 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
3304 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003305 """
3306 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
3307 else:
3308 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3309
3310
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003311 def test_sess_cache_off(self):
3312 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003313 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3314 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003315 """
3316 self.assertEqual(0x0, SESS_CACHE_OFF)
3317
3318
3319 def test_sess_cache_client(self):
3320 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003321 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3322 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003323 """
3324 self.assertEqual(0x1, SESS_CACHE_CLIENT)
3325
3326
3327 def test_sess_cache_server(self):
3328 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003329 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3330 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003331 """
3332 self.assertEqual(0x2, SESS_CACHE_SERVER)
3333
3334
3335 def test_sess_cache_both(self):
3336 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003337 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3338 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003339 """
3340 self.assertEqual(0x3, SESS_CACHE_BOTH)
3341
3342
3343 def test_sess_cache_no_auto_clear(self):
3344 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003345 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3346 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3347 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003348 """
3349 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
3350
3351
3352 def test_sess_cache_no_internal_lookup(self):
3353 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003354 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3355 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3356 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003357 """
3358 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
3359
3360
3361 def test_sess_cache_no_internal_store(self):
3362 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003363 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3364 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3365 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003366 """
3367 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
3368
3369
3370 def test_sess_cache_no_internal(self):
3371 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003372 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3373 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
3374 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003375 """
3376 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
3377
3378
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04003379
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003380class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05003381 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003382 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003383 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003384 def _server(self, sock):
3385 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003386 Create a new server-side SSL :py:obj:`Connection` object wrapped around
3387 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003388 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003389 # Create the server side Connection. This is mostly setup boilerplate
3390 # - use TLSv1, use a particular certificate, etc.
3391 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003392 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
3393 server_ctx.set_verify(VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE, verify_cb)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003394 server_store = server_ctx.get_cert_store()
3395 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3396 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3397 server_ctx.check_privatekey()
3398 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003399 # Here the Connection is actually created. If None is passed as the 2nd
3400 # parameter, it indicates a memory BIO should be created.
3401 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003402 server_conn.set_accept_state()
3403 return server_conn
3404
3405
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003406 def _client(self, sock):
3407 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003408 Create a new client-side SSL :py:obj:`Connection` object wrapped around
3409 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003410 """
3411 # Now create the client side Connection. Similar boilerplate to the
3412 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003413 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003414 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
3415 client_ctx.set_verify(VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE, verify_cb)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003416 client_store = client_ctx.get_cert_store()
3417 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
3418 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
3419 client_ctx.check_privatekey()
3420 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003421 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003422 client_conn.set_connect_state()
3423 return client_conn
3424
3425
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003426 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003427 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003428 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003429 reading from the output of each and writing those bytes to the input of
3430 the other and in this way establish a connection and exchange
3431 application-level bytes with each other.
3432 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003433 server_conn = self._server(None)
3434 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003435
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003436 # There should be no key or nonces yet.
3437 self.assertIdentical(server_conn.master_key(), None)
3438 self.assertIdentical(server_conn.client_random(), None)
3439 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003440
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003441 # First, the handshake needs to happen. We'll deliver bytes back and
3442 # forth between the client and server until neither of them feels like
3443 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003444 self.assertIdentical(
3445 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003446
3447 # Now that the handshake is done, there should be a key and nonces.
3448 self.assertNotIdentical(server_conn.master_key(), None)
3449 self.assertNotIdentical(server_conn.client_random(), None)
3450 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04003451 self.assertEquals(server_conn.client_random(), client_conn.client_random())
3452 self.assertEquals(server_conn.server_random(), client_conn.server_random())
3453 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
3454 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003455
3456 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003457 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05003458
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003459 server_conn.write(important_message)
3460 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003461 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003462 (client_conn, important_message))
3463
3464 client_conn.write(important_message[::-1])
3465 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003466 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003467 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003468
3469
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003470 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003471 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003472 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003473
3474 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09003475 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003476 this test fails, there must be a problem outside the memory BIO
3477 code, as no memory BIO is involved here). Even though this isn't a
3478 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003479 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04003480 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003481
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003482 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05003483 client_conn.send(important_message)
3484 msg = server_conn.recv(1024)
3485 self.assertEqual(msg, important_message)
3486
3487 # Again in the other direction, just for fun.
3488 important_message = important_message[::-1]
3489 server_conn.send(important_message)
3490 msg = client_conn.recv(1024)
3491 self.assertEqual(msg, important_message)
3492
3493
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04003494 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003495 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003496 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
3497 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003498 """
3499 context = Context(SSLv3_METHOD)
3500 client = socket()
3501 clientSSL = Connection(context, client)
Alex Gaynor43307782015-09-04 09:05:45 -04003502 self.assertRaises(TypeError, clientSSL.bio_read, 100)
3503 self.assertRaises(TypeError, clientSSL.bio_write, "foo")
Alex Gaynor7e8b61e2015-09-04 13:13:05 -04003504 self.assertRaises(TypeError, clientSSL.bio_shutdown)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003505
3506
3507 def test_outgoingOverflow(self):
3508 """
3509 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09003510 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003511 returned and that many bytes from the beginning of the input can be
3512 read from the other end of the connection.
3513 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003514 server = self._server(None)
3515 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003516
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003517 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003518
3519 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003520 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003521 # Sanity check. We're trying to test what happens when the entire
3522 # input can't be sent. If the entire input was sent, this test is
3523 # meaningless.
3524 self.assertTrue(sent < size)
3525
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003526 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003527 self.assertIdentical(receiver, server)
3528
3529 # We can rely on all of these bytes being received at once because
3530 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
3531 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003532
3533
3534 def test_shutdown(self):
3535 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003536 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
3537 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003538 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003539 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003540 server.bio_shutdown()
3541 e = self.assertRaises(Error, server.recv, 1024)
3542 # We don't want WantReadError or ZeroReturnError or anything - it's a
3543 # handshake failure.
3544 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003545
3546
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003547 def test_unexpectedEndOfFile(self):
3548 """
3549 If the connection is lost before an orderly SSL shutdown occurs,
3550 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
3551 "Unexpected EOF".
3552 """
3553 server_conn, client_conn = self._loopback()
3554 client_conn.sock_shutdown(SHUT_RDWR)
3555 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
3556 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
3557
3558
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003559 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003560 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003561 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 -04003562
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003563 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003564 before the client and server are connected to each other. This
3565 function should specify a list of CAs for the server to send to the
3566 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09003567 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003568 times.
3569 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003570 server = self._server(None)
3571 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003572 self.assertEqual(client.get_client_ca_list(), [])
3573 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003574 ctx = server.get_context()
3575 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003576 self.assertEqual(client.get_client_ca_list(), [])
3577 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003578 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003579 self.assertEqual(client.get_client_ca_list(), expected)
3580 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003581
3582
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003583 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003584 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003585 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003586 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003587 """
3588 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003589 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
3590 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
3591 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003592
3593
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003594 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003595 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003596 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003597 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09003598 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003599 after the connection is set up.
3600 """
3601 def no_ca(ctx):
3602 ctx.set_client_ca_list([])
3603 return []
3604 self._check_client_ca_list(no_ca)
3605
3606
3607 def test_set_one_ca_list(self):
3608 """
3609 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003610 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003611 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003612 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003613 X509Name after the connection is set up.
3614 """
3615 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3616 cadesc = cacert.get_subject()
3617 def single_ca(ctx):
3618 ctx.set_client_ca_list([cadesc])
3619 return [cadesc]
3620 self._check_client_ca_list(single_ca)
3621
3622
3623 def test_set_multiple_ca_list(self):
3624 """
3625 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003626 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003627 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003628 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003629 X509Names after the connection is set up.
3630 """
3631 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3632 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3633
3634 sedesc = secert.get_subject()
3635 cldesc = clcert.get_subject()
3636
3637 def multiple_ca(ctx):
3638 L = [sedesc, cldesc]
3639 ctx.set_client_ca_list(L)
3640 return L
3641 self._check_client_ca_list(multiple_ca)
3642
3643
3644 def test_reset_ca_list(self):
3645 """
3646 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09003647 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003648 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003649 """
3650 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3651 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3652 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3653
3654 cadesc = cacert.get_subject()
3655 sedesc = secert.get_subject()
3656 cldesc = clcert.get_subject()
3657
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003658 def changed_ca(ctx):
3659 ctx.set_client_ca_list([sedesc, cldesc])
3660 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003661 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003662 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003663
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003664
3665 def test_mutated_ca_list(self):
3666 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003667 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003668 afterwards, this does not affect the list of CA names sent to the
3669 client.
3670 """
3671 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3672 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3673
3674 cadesc = cacert.get_subject()
3675 sedesc = secert.get_subject()
3676
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003677 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003678 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003679 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003680 L.append(sedesc)
3681 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003682 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003683
3684
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003685 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003686 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003687 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003688 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003689 """
3690 ctx = Context(TLSv1_METHOD)
3691 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003692 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003693 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003694 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003695
3696
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003697 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003698 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003699 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09003700 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003701 """
3702 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3703 cadesc = cacert.get_subject()
3704 def single_ca(ctx):
3705 ctx.add_client_ca(cacert)
3706 return [cadesc]
3707 self._check_client_ca_list(single_ca)
3708
3709
3710 def test_multiple_add_client_ca(self):
3711 """
3712 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09003713 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003714 """
3715 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3716 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3717
3718 cadesc = cacert.get_subject()
3719 sedesc = secert.get_subject()
3720
3721 def multiple_ca(ctx):
3722 ctx.add_client_ca(cacert)
3723 ctx.add_client_ca(secert)
3724 return [cadesc, sedesc]
3725 self._check_client_ca_list(multiple_ca)
3726
3727
3728 def test_set_and_add_client_ca(self):
3729 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003730 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
3731 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003732 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003733 """
3734 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3735 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3736 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3737
3738 cadesc = cacert.get_subject()
3739 sedesc = secert.get_subject()
3740 cldesc = clcert.get_subject()
3741
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003742 def mixed_set_add_ca(ctx):
3743 ctx.set_client_ca_list([cadesc, sedesc])
3744 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003745 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003746 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003747
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003748
3749 def test_set_after_add_client_ca(self):
3750 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003751 A call to :py:obj:`Context.set_client_ca_list` after a call to
3752 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003753 call with the names specified by the latter cal.
3754 """
3755 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3756 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3757 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3758
3759 cadesc = cacert.get_subject()
3760 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003761
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003762 def set_replaces_add_ca(ctx):
3763 ctx.add_client_ca(clcert)
3764 ctx.set_client_ca_list([cadesc])
3765 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003766 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003767 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003768
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003769
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003770
3771class ConnectionBIOTests(TestCase):
3772 """
3773 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3774 """
3775 def test_wantReadError(self):
3776 """
3777 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
3778 if there are no bytes available to be read from the BIO.
3779 """
3780 ctx = Context(TLSv1_METHOD)
3781 conn = Connection(ctx, None)
3782 self.assertRaises(WantReadError, conn.bio_read, 1024)
3783
3784
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003785 def test_buffer_size(self):
3786 """
3787 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3788 number of bytes to read and return.
3789 """
3790 ctx = Context(TLSv1_METHOD)
3791 conn = Connection(ctx, None)
3792 conn.set_connect_state()
3793 try:
3794 conn.do_handshake()
3795 except WantReadError:
3796 pass
3797 data = conn.bio_read(2)
3798 self.assertEqual(2, len(data))
3799
3800
3801 if not PY3:
3802 def test_buffer_size_long(self):
3803 """
3804 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3805 :py:obj:`long` as well as :py:obj:`int`.
3806 """
3807 ctx = Context(TLSv1_METHOD)
3808 conn = Connection(ctx, None)
3809 conn.set_connect_state()
3810 try:
3811 conn.do_handshake()
3812 except WantReadError:
3813 pass
3814 data = conn.bio_read(long(2))
3815 self.assertEqual(2, len(data))
3816
3817
3818
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003819
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003820class InfoConstantTests(TestCase):
3821 """
3822 Tests for assorted constants exposed for use in info callbacks.
3823 """
3824 def test_integers(self):
3825 """
3826 All of the info constants are integers.
3827
3828 This is a very weak test. It would be nice to have one that actually
3829 verifies that as certain info events happen, the value passed to the
3830 info callback matches up with the constant exposed by OpenSSL.SSL.
3831 """
3832 for const in [
3833 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3834 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3835 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3836 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3837 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
3838 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
3839
3840 self.assertTrue(isinstance(const, int))
3841
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003842
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003843if __name__ == '__main__':
3844 main()