blob: d54c8396dd549dc1b18e7780f7b5f83bf07bf79f [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
Alex Gaynor1aabb2e2015-09-05 13:35:18 -040018import pytest
19
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -040020from six import PY3, text_type, u
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050021
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040022from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080023from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040024from OpenSSL.crypto import dump_privatekey, load_privatekey
25from OpenSSL.crypto import dump_certificate, load_certificate
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040026from OpenSSL.crypto import get_elliptic_curves
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040027
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040028from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
29from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040030from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040031from OpenSSL.SSL import (
32 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
33 TLSv1_1_METHOD, TLSv1_2_METHOD)
34from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040035from OpenSSL.SSL import (
36 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040037
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040038from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050039 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
40 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
41 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
42
43from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070044 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050045from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070046 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040047
Cory Benfieldba1820d2015-04-13 17:39:12 -040048from OpenSSL._util import lib as _lib
49
Jean-Paul Calderone17eca482015-04-13 20:31:07 -040050from OpenSSL.test.util import WARNING_TYPE_EXPECTED, NON_ASCII, TestCase, b
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040051from OpenSSL.test.test_crypto import (
Jean-Paul Calderoneda6399a2015-04-13 20:52:29 -040052 cleartextCertificatePEM, cleartextPrivateKeyPEM,
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040053 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
54 root_cert_pem)
55
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050056try:
57 from OpenSSL.SSL import OP_NO_QUERY_MTU
58except ImportError:
59 OP_NO_QUERY_MTU = None
60try:
61 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
62except ImportError:
63 OP_COOKIE_EXCHANGE = None
64try:
65 from OpenSSL.SSL import OP_NO_TICKET
66except ImportError:
67 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040068
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040069try:
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -040070 from OpenSSL.SSL import OP_NO_COMPRESSION
71except ImportError:
72 OP_NO_COMPRESSION = None
73
74try:
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040075 from OpenSSL.SSL import MODE_RELEASE_BUFFERS
76except ImportError:
77 MODE_RELEASE_BUFFERS = None
78
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040079try:
80 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
81except ImportError:
82 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
83
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040084from OpenSSL.SSL import (
85 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
86 SSL_ST_OK, SSL_ST_RENEGOTIATE,
87 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
88 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
89 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
90 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040091
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040092# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
93# to use)
94dhparam = """\
95-----BEGIN DH PARAMETERS-----
96MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
97-----END DH PARAMETERS-----
98"""
99
100
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400101def join_bytes_or_unicode(prefix, suffix):
102 """
103 Join two path components of either ``bytes`` or ``unicode``.
104
105 The return type is the same as the type of ``prefix``.
106 """
107 # If the types are the same, nothing special is necessary.
108 if type(prefix) == type(suffix):
109 return join(prefix, suffix)
110
111 # Otherwise, coerce suffix to the type of prefix.
112 if isinstance(prefix, text_type):
113 return join(prefix, suffix.decode(getfilesystemencoding()))
114 else:
115 return join(prefix, suffix.encode(getfilesystemencoding()))
116
117
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400118def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400119 return ok
120
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400121
Rick Deanb1ccd562009-07-09 23:52:39 -0500122def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400123 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400124 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400125 """
126 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500127 port = socket()
128 port.bind(('', 0))
129 port.listen(1)
130 client = socket()
131 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400132 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400133 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500134 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500135
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400136 # Let's pass some unencrypted data to make sure our socket connection is
137 # fine. Just one byte, so we don't have to worry about buffers getting
138 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400139 server.send(b("x"))
140 assert client.recv(1024) == b("x")
141 client.send(b("y"))
142 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500143
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400144 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400145 server.setblocking(False)
146 client.setblocking(False)
Jim Shaver46f28912015-05-29 19:32:16 -0400147
Rick Deanb1ccd562009-07-09 23:52:39 -0500148 return (server, client)
149
150
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400151
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400152def handshake(client, server):
153 conns = [client, server]
154 while conns:
155 for conn in conns:
156 try:
157 conn.do_handshake()
158 except WantReadError:
159 pass
160 else:
161 conns.remove(conn)
162
163
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400164def _create_certificate_chain():
165 """
166 Construct and return a chain of certificates.
167
168 1. A new self-signed certificate authority certificate (cacert)
169 2. A new intermediate certificate signed by cacert (icert)
170 3. A new server certificate signed by icert (scert)
171 """
172 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
173
174 # Step 1
175 cakey = PKey()
176 cakey.generate_key(TYPE_RSA, 512)
177 cacert = X509()
178 cacert.get_subject().commonName = "Authority Certificate"
179 cacert.set_issuer(cacert.get_subject())
180 cacert.set_pubkey(cakey)
181 cacert.set_notBefore(b("20000101000000Z"))
182 cacert.set_notAfter(b("20200101000000Z"))
183 cacert.add_extensions([caext])
184 cacert.set_serial_number(0)
185 cacert.sign(cakey, "sha1")
186
187 # Step 2
188 ikey = PKey()
189 ikey.generate_key(TYPE_RSA, 512)
190 icert = X509()
191 icert.get_subject().commonName = "Intermediate Certificate"
192 icert.set_issuer(cacert.get_subject())
193 icert.set_pubkey(ikey)
194 icert.set_notBefore(b("20000101000000Z"))
195 icert.set_notAfter(b("20200101000000Z"))
196 icert.add_extensions([caext])
197 icert.set_serial_number(0)
198 icert.sign(cakey, "sha1")
199
200 # Step 3
201 skey = PKey()
202 skey.generate_key(TYPE_RSA, 512)
203 scert = X509()
204 scert.get_subject().commonName = "Server Certificate"
205 scert.set_issuer(icert.get_subject())
206 scert.set_pubkey(skey)
207 scert.set_notBefore(b("20000101000000Z"))
208 scert.set_notAfter(b("20200101000000Z"))
209 scert.add_extensions([
210 X509Extension(b('basicConstraints'), True, b('CA:false'))])
211 scert.set_serial_number(0)
212 scert.sign(ikey, "sha1")
213
214 return [(cakey, cacert), (ikey, icert), (skey, scert)]
215
216
217
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400218class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400219 """
220 Helper mixin which defines methods for creating a connected socket pair and
221 for forcing two connected SSL sockets to talk to each other via memory BIOs.
222 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500223 def _loopbackClientFactory(self, socket):
224 client = Connection(Context(TLSv1_METHOD), socket)
225 client.set_connect_state()
226 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400227
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500228
229 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400230 ctx = Context(TLSv1_METHOD)
231 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
232 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500233 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400234 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500235 return server
236
237
238 def _loopback(self, serverFactory=None, clientFactory=None):
239 if serverFactory is None:
240 serverFactory = self._loopbackServerFactory
241 if clientFactory is None:
242 clientFactory = self._loopbackClientFactory
243
244 (server, client) = socket_pair()
245 server = serverFactory(server)
246 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400247
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400248 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400249
250 server.setblocking(True)
251 client.setblocking(True)
252 return server, client
253
254
255 def _interactInMemory(self, client_conn, server_conn):
256 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900257 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400258 objects. Copy bytes back and forth between their send/receive buffers
259 for as long as there is anything to copy. When there is nothing more
Jonathan Ballet648875f2011-07-16 14:14:58 +0900260 to copy, return :py:obj:`None`. If one of them actually manages to deliver
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400261 some application bytes, return a two-tuple of the connection from which
262 the bytes were read and the bytes themselves.
263 """
264 wrote = True
265 while wrote:
266 # Loop until neither side has anything to say
267 wrote = False
268
269 # Copy stuff from each side's send buffer to the other side's
270 # receive buffer.
271 for (read, write) in [(client_conn, server_conn),
272 (server_conn, client_conn)]:
273
274 # Give the side a chance to generate some more bytes, or
275 # succeed.
276 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400277 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400278 except WantReadError:
279 # It didn't succeed, so we'll hope it generated some
280 # output.
281 pass
282 else:
283 # It did succeed, so we'll stop now and let the caller deal
284 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400285 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400286
287 while True:
288 # Keep copying as long as there's more stuff there.
289 try:
290 dirty = read.bio_read(4096)
291 except WantReadError:
292 # Okay, nothing more waiting to be sent. Stop
293 # processing this send buffer.
294 break
295 else:
296 # Keep track of the fact that someone generated some
297 # output.
298 wrote = True
299 write.bio_write(dirty)
300
301
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400302 def _handshakeInMemory(self, client_conn, server_conn):
Jean-Paul Calderoneb2b40782014-05-06 08:47:40 -0400303 """
304 Perform the TLS handshake between two :py:class:`Connection` instances
305 connected to each other via memory BIOs.
306 """
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400307 client_conn.set_connect_state()
308 server_conn.set_accept_state()
309
310 for conn in [client_conn, server_conn]:
311 try:
312 conn.do_handshake()
313 except WantReadError:
314 pass
315
316 self._interactInMemory(client_conn, server_conn)
317
318
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400319
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400320class VersionTests(TestCase):
321 """
322 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900323 :py:obj:`OpenSSL.SSL.SSLeay_version` and
324 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400325 """
326 def test_OPENSSL_VERSION_NUMBER(self):
327 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900328 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400329 byte and the patch, fix, minor, and major versions in the
330 nibbles above that.
331 """
332 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
333
334
335 def test_SSLeay_version(self):
336 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900337 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400338 one of a number of version strings based on that indicator.
339 """
340 versions = {}
341 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
342 SSLEAY_PLATFORM, SSLEAY_DIR]:
343 version = SSLeay_version(t)
344 versions[version] = t
345 self.assertTrue(isinstance(version, bytes))
346 self.assertEqual(len(versions), 5)
347
348
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400349
350class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400351 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900352 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400353 """
354 def test_method(self):
355 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900356 :py:obj:`Context` can be instantiated with one of :py:obj:`SSLv2_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400357 :py:obj:`SSLv3_METHOD`, :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
358 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400359 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400360 methods = [
361 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
362 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400363 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400364
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400365
366 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
367 for meth in maybe:
368 try:
369 Context(meth)
370 except (Error, ValueError):
371 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
372 # don't. Difficult to say in advance.
373 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400374
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400375 self.assertRaises(TypeError, Context, "")
376 self.assertRaises(ValueError, Context, 10)
377
378
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500379 if not PY3:
380 def test_method_long(self):
381 """
382 On Python 2 :py:class:`Context` accepts values of type
383 :py:obj:`long` as well as :py:obj:`int`.
384 """
385 Context(long(TLSv1_METHOD))
386
387
388
Rick Deane15b1472009-07-09 15:53:42 -0500389 def test_type(self):
390 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900391 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400392 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500393 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400394 self.assertIdentical(Context, ContextType)
395 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500396
397
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400398 def test_use_privatekey(self):
399 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900400 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400401 """
402 key = PKey()
403 key.generate_key(TYPE_RSA, 128)
404 ctx = Context(TLSv1_METHOD)
405 ctx.use_privatekey(key)
406 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400407
408
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800409 def test_use_privatekey_file_missing(self):
410 """
411 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error`
412 when passed the name of a file which does not exist.
413 """
414 ctx = Context(TLSv1_METHOD)
415 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
416
417
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400418 def _use_privatekey_file_test(self, pemfile, filetype):
419 """
420 Verify that calling ``Context.use_privatekey_file`` with the given
421 arguments does not raise an exception.
422 """
423 key = PKey()
424 key.generate_key(TYPE_RSA, 128)
425
426 with open(pemfile, "wt") as pem:
427 pem.write(
428 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
429 )
430
431 ctx = Context(TLSv1_METHOD)
432 ctx.use_privatekey_file(pemfile, filetype)
433
434
435 def test_use_privatekey_file_bytes(self):
436 """
437 A private key can be specified from a file by passing a ``bytes``
438 instance giving the file name to ``Context.use_privatekey_file``.
439 """
440 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400441 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400442 FILETYPE_PEM,
443 )
444
445
446 def test_use_privatekey_file_unicode(self):
447 """
448 A private key can be specified from a file by passing a ``unicode``
449 instance giving the file name to ``Context.use_privatekey_file``.
450 """
451 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400452 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400453 FILETYPE_PEM,
454 )
455
456
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500457 if not PY3:
458 def test_use_privatekey_file_long(self):
459 """
460 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
461 filetype of type :py:obj:`long` as well as :py:obj:`int`.
462 """
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400463 self._use_privatekey_file_test(self.mktemp(), long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500464
465
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800466 def test_use_certificate_wrong_args(self):
467 """
468 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
469 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as an
470 argument.
471 """
472 ctx = Context(TLSv1_METHOD)
473 self.assertRaises(TypeError, ctx.use_certificate)
474 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
475 self.assertRaises(TypeError, ctx.use_certificate, X509(), "hello, world")
476
477
478 def test_use_certificate_uninitialized(self):
479 """
480 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
481 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
482 initialized (ie, which does not actually have any certificate data).
483 """
484 ctx = Context(TLSv1_METHOD)
485 self.assertRaises(Error, ctx.use_certificate, X509())
486
487
488 def test_use_certificate(self):
489 """
490 :py:obj:`Context.use_certificate` sets the certificate which will be
491 used to identify connections created using the context.
492 """
493 # TODO
494 # Hard to assert anything. But we could set a privatekey then ask
495 # OpenSSL if the cert and key agree using check_privatekey. Then as
496 # long as check_privatekey works right we're good...
497 ctx = Context(TLSv1_METHOD)
498 ctx.use_certificate(load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
499
500
501 def test_use_certificate_file_wrong_args(self):
502 """
503 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
504 called with zero arguments or more than two arguments, or if the first
505 argument is not a byte string or the second argumnent is not an integer.
506 """
507 ctx = Context(TLSv1_METHOD)
508 self.assertRaises(TypeError, ctx.use_certificate_file)
509 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile", object())
510 self.assertRaises(
511 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM, object())
512 self.assertRaises(
513 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
514 self.assertRaises(
515 TypeError, ctx.use_certificate_file, b"somefile", object())
516
517
518 def test_use_certificate_file_missing(self):
519 """
520 :py:obj:`Context.use_certificate_file` raises
521 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does not
522 exist.
523 """
524 ctx = Context(TLSv1_METHOD)
525 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
526
527
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400528 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800529 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400530 Verify that calling ``Context.use_certificate_file`` with the given
531 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800532 """
533 # TODO
534 # Hard to assert anything. But we could set a privatekey then ask
535 # OpenSSL if the cert and key agree using check_privatekey. Then as
536 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400537 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800538 pem_file.write(cleartextCertificatePEM)
539
540 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400541 ctx.use_certificate_file(certificate_file)
542
543
544 def test_use_certificate_file_bytes(self):
545 """
546 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
547 ``bytes`` filename) which will be used to identify connections created
548 using the context.
549 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400550 filename = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400551 self._use_certificate_file_test(filename)
552
553
554 def test_use_certificate_file_unicode(self):
555 """
556 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
557 ``bytes`` filename) which will be used to identify connections created
558 using the context.
559 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400560 filename = self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400561 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800562
563
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500564 if not PY3:
565 def test_use_certificate_file_long(self):
566 """
567 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
568 filetype of type :py:obj:`long` as well as :py:obj:`int`.
569 """
570 pem_filename = self.mktemp()
571 with open(pem_filename, "wb") as pem_file:
572 pem_file.write(cleartextCertificatePEM)
573
574 ctx = Context(TLSv1_METHOD)
575 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
576
577
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500578 def test_check_privatekey_valid(self):
579 """
580 :py:obj:`Context.check_privatekey` returns :py:obj:`None` if the
581 :py:obj:`Context` instance has been configured to use a matched key and
582 certificate pair.
583 """
584 key = load_privatekey(FILETYPE_PEM, client_key_pem)
585 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
586 context = Context(TLSv1_METHOD)
587 context.use_privatekey(key)
588 context.use_certificate(cert)
589 self.assertIs(None, context.check_privatekey())
590
591
592 def test_check_privatekey_invalid(self):
593 """
594 :py:obj:`Context.check_privatekey` raises :py:obj:`Error` if the
595 :py:obj:`Context` instance has been configured to use a key and
596 certificate pair which don't relate to each other.
597 """
598 key = load_privatekey(FILETYPE_PEM, client_key_pem)
599 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
600 context = Context(TLSv1_METHOD)
601 context.use_privatekey(key)
602 context.use_certificate(cert)
603 self.assertRaises(Error, context.check_privatekey)
604
605
606 def test_check_privatekey_wrong_args(self):
607 """
608 :py:obj:`Context.check_privatekey` raises :py:obj:`TypeError` if called
609 with other than no arguments.
610 """
611 context = Context(TLSv1_METHOD)
612 self.assertRaises(TypeError, context.check_privatekey, object())
613
614
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400615 def test_set_app_data_wrong_args(self):
616 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900617 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called with other than
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400618 one argument.
619 """
620 context = Context(TLSv1_METHOD)
621 self.assertRaises(TypeError, context.set_app_data)
622 self.assertRaises(TypeError, context.set_app_data, None, None)
623
624
625 def test_get_app_data_wrong_args(self):
626 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900627 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400628 arguments.
629 """
630 context = Context(TLSv1_METHOD)
631 self.assertRaises(TypeError, context.get_app_data, None)
632
633
634 def test_app_data(self):
635 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900636 :py:obj:`Context.set_app_data` stores an object for later retrieval using
637 :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400638 """
639 app_data = object()
640 context = Context(TLSv1_METHOD)
641 context.set_app_data(app_data)
642 self.assertIdentical(context.get_app_data(), app_data)
643
644
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400645 def test_set_options_wrong_args(self):
646 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900647 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with the wrong
648 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400649 """
650 context = Context(TLSv1_METHOD)
651 self.assertRaises(TypeError, context.set_options)
652 self.assertRaises(TypeError, context.set_options, None)
653 self.assertRaises(TypeError, context.set_options, 1, None)
654
655
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500656 def test_set_options(self):
657 """
658 :py:obj:`Context.set_options` returns the new options value.
659 """
660 context = Context(TLSv1_METHOD)
661 options = context.set_options(OP_NO_SSLv2)
662 self.assertTrue(OP_NO_SSLv2 & options)
663
664
665 if not PY3:
666 def test_set_options_long(self):
667 """
668 On Python 2 :py:obj:`Context.set_options` accepts values of type
669 :py:obj:`long` as well as :py:obj:`int`.
670 """
671 context = Context(TLSv1_METHOD)
672 options = context.set_options(long(OP_NO_SSLv2))
673 self.assertTrue(OP_NO_SSLv2 & options)
674
675
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300676 def test_set_mode_wrong_args(self):
677 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400678 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with the wrong
679 number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300680 """
681 context = Context(TLSv1_METHOD)
682 self.assertRaises(TypeError, context.set_mode)
683 self.assertRaises(TypeError, context.set_mode, None)
684 self.assertRaises(TypeError, context.set_mode, 1, None)
685
686
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400687 if MODE_RELEASE_BUFFERS is not None:
688 def test_set_mode(self):
689 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400690 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the newly
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400691 set mode.
692 """
693 context = Context(TLSv1_METHOD)
694 self.assertTrue(
695 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500696
697 if not PY3:
698 def test_set_mode_long(self):
699 """
700 On Python 2 :py:obj:`Context.set_mode` accepts values of type
701 :py:obj:`long` as well as :py:obj:`int`.
702 """
703 context = Context(TLSv1_METHOD)
704 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
705 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400706 else:
707 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
708
709
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400710 def test_set_timeout_wrong_args(self):
711 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900712 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with the wrong
713 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400714 """
715 context = Context(TLSv1_METHOD)
716 self.assertRaises(TypeError, context.set_timeout)
717 self.assertRaises(TypeError, context.set_timeout, None)
718 self.assertRaises(TypeError, context.set_timeout, 1, None)
719
720
721 def test_get_timeout_wrong_args(self):
722 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900723 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400724 """
725 context = Context(TLSv1_METHOD)
726 self.assertRaises(TypeError, context.get_timeout, None)
727
728
729 def test_timeout(self):
730 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900731 :py:obj:`Context.set_timeout` sets the session timeout for all connections
732 created using the context object. :py:obj:`Context.get_timeout` retrieves this
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400733 value.
734 """
735 context = Context(TLSv1_METHOD)
736 context.set_timeout(1234)
737 self.assertEquals(context.get_timeout(), 1234)
738
739
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500740 if not PY3:
741 def test_timeout_long(self):
742 """
743 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
744 `long` as well as int.
745 """
746 context = Context(TLSv1_METHOD)
747 context.set_timeout(long(1234))
748 self.assertEquals(context.get_timeout(), 1234)
749
750
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400751 def test_set_verify_depth_wrong_args(self):
752 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900753 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called with the wrong
754 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400755 """
756 context = Context(TLSv1_METHOD)
757 self.assertRaises(TypeError, context.set_verify_depth)
758 self.assertRaises(TypeError, context.set_verify_depth, None)
759 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
760
761
762 def test_get_verify_depth_wrong_args(self):
763 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900764 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400765 """
766 context = Context(TLSv1_METHOD)
767 self.assertRaises(TypeError, context.get_verify_depth, None)
768
769
770 def test_verify_depth(self):
771 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900772 :py:obj:`Context.set_verify_depth` sets the number of certificates in a chain
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400773 to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900774 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400775 """
776 context = Context(TLSv1_METHOD)
777 context.set_verify_depth(11)
778 self.assertEquals(context.get_verify_depth(), 11)
779
780
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500781 if not PY3:
782 def test_verify_depth_long(self):
783 """
784 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
785 type `long` as well as int.
786 """
787 context = Context(TLSv1_METHOD)
788 context.set_verify_depth(long(11))
789 self.assertEquals(context.get_verify_depth(), 11)
790
791
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400792 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400793 """
794 Write a new private key out to a new file, encrypted using the given
795 passphrase. Return the path to the new file.
796 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400797 key = PKey()
798 key.generate_key(TYPE_RSA, 128)
799 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400800 fObj = open(pemFile, 'w')
801 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
802 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400803 fObj.close()
804 return pemFile
805
806
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400807 def test_set_passwd_cb_wrong_args(self):
808 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900809 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called with the
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400810 wrong arguments or with a non-callable first argument.
811 """
812 context = Context(TLSv1_METHOD)
813 self.assertRaises(TypeError, context.set_passwd_cb)
814 self.assertRaises(TypeError, context.set_passwd_cb, None)
815 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
816
817
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400818 def test_set_passwd_cb(self):
819 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900820 :py:obj:`Context.set_passwd_cb` accepts a callable which will be invoked when
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400821 a private key is loaded from an encrypted PEM.
822 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400823 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400824 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400825 calledWith = []
826 def passphraseCallback(maxlen, verify, extra):
827 calledWith.append((maxlen, verify, extra))
828 return passphrase
829 context = Context(TLSv1_METHOD)
830 context.set_passwd_cb(passphraseCallback)
831 context.use_privatekey_file(pemFile)
832 self.assertTrue(len(calledWith), 1)
833 self.assertTrue(isinstance(calledWith[0][0], int))
834 self.assertTrue(isinstance(calledWith[0][1], int))
835 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400836
837
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400838 def test_passwd_callback_exception(self):
839 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900840 :py:obj:`Context.use_privatekey_file` propagates any exception raised by the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400841 passphrase callback.
842 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400843 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400844 def passphraseCallback(maxlen, verify, extra):
845 raise RuntimeError("Sorry, I am a fail.")
846
847 context = Context(TLSv1_METHOD)
848 context.set_passwd_cb(passphraseCallback)
849 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
850
851
852 def test_passwd_callback_false(self):
853 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900854 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400855 passphrase callback returns a false value.
856 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400857 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400858 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500859 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400860
861 context = Context(TLSv1_METHOD)
862 context.set_passwd_cb(passphraseCallback)
863 self.assertRaises(Error, context.use_privatekey_file, pemFile)
864
865
866 def test_passwd_callback_non_string(self):
867 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900868 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400869 passphrase callback returns a true non-string value.
870 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400871 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400872 def passphraseCallback(maxlen, verify, extra):
873 return 10
874
875 context = Context(TLSv1_METHOD)
876 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800877 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400878
879
880 def test_passwd_callback_too_long(self):
881 """
882 If the passphrase returned by the passphrase callback returns a string
883 longer than the indicated maximum length, it is truncated.
884 """
885 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400886 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400887 pemFile = self._write_encrypted_pem(passphrase)
888 def passphraseCallback(maxlen, verify, extra):
889 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400890 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400891
892 context = Context(TLSv1_METHOD)
893 context.set_passwd_cb(passphraseCallback)
894 # This shall succeed because the truncated result is the correct
895 # passphrase.
896 context.use_privatekey_file(pemFile)
897
898
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400899 def test_set_info_callback(self):
900 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900901 :py:obj:`Context.set_info_callback` accepts a callable which will be invoked
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400902 when certain information about an SSL connection is available.
903 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500904 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400905
906 clientSSL = Connection(Context(TLSv1_METHOD), client)
907 clientSSL.set_connect_state()
908
909 called = []
910 def info(conn, where, ret):
911 called.append((conn, where, ret))
912 context = Context(TLSv1_METHOD)
913 context.set_info_callback(info)
914 context.use_certificate(
915 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
916 context.use_privatekey(
917 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
918
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400919 serverSSL = Connection(context, server)
920 serverSSL.set_accept_state()
921
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500922 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400923
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500924 # The callback must always be called with a Connection instance as the
925 # first argument. It would probably be better to split this into
926 # separate tests for client and server side info callbacks so we could
927 # assert it is called with the right Connection instance. It would
928 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500929 notConnections = [
930 conn for (conn, where, ret) in called
931 if not isinstance(conn, Connection)]
932 self.assertEqual(
933 [], notConnections,
934 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400935
936
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400937 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400938 """
939 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400940 its :py:obj:`load_verify_locations` method with the given arguments.
941 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400942 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500943 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400944
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400945 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400946 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400947 # Require that the server certificate verify properly or the
948 # connection will fail.
949 clientContext.set_verify(
950 VERIFY_PEER,
951 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
952
953 clientSSL = Connection(clientContext, client)
954 clientSSL.set_connect_state()
955
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400956 serverContext = Context(TLSv1_METHOD)
957 serverContext.use_certificate(
958 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
959 serverContext.use_privatekey(
960 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
961
962 serverSSL = Connection(serverContext, server)
963 serverSSL.set_accept_state()
964
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400965 # Without load_verify_locations above, the handshake
966 # will fail:
967 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
968 # 'certificate verify failed')]
969 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400970
971 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400972 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400973
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500974
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400975 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400976 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400977 Verify that if path to a file containing a certificate is passed to
978 ``Context.load_verify_locations`` for the ``cafile`` parameter, that
979 certificate is used as a trust root for the purposes of verifying
980 connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400981 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400982 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400983 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400984 fObj.close()
985
986 self._load_verify_locations_test(cafile)
987
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400988
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400989 def test_load_verify_bytes_cafile(self):
990 """
991 :py:obj:`Context.load_verify_locations` accepts a file name as a
992 ``bytes`` instance and uses the certificates within for verification
993 purposes.
994 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400995 cafile = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400996 self._load_verify_cafile(cafile)
997
998
999 def test_load_verify_unicode_cafile(self):
1000 """
1001 :py:obj:`Context.load_verify_locations` accepts a file name as a
1002 ``unicode`` instance and uses the certificates within for verification
1003 purposes.
1004 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001005 self._load_verify_cafile(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001006 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001007 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001008
1009
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001010 def test_load_verify_invalid_file(self):
1011 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001012 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when passed a
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001013 non-existent cafile.
1014 """
1015 clientContext = Context(TLSv1_METHOD)
1016 self.assertRaises(
1017 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001018
1019
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001020 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001021 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001022 Verify that if path to a directory containing certificate files is
1023 passed to ``Context.load_verify_locations`` for the ``capath``
1024 parameter, those certificates are used as trust roots for the purposes
1025 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001026 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001027 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001028 # Hash values computed manually with c_rehash to avoid depending on
1029 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1030 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001031 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001032 cafile = join_bytes_or_unicode(capath, name)
1033 with open(cafile, 'w') as fObj:
1034 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001035
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001036 self._load_verify_locations_test(None, capath)
1037
1038
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001039 def test_load_verify_directory_bytes_capath(self):
1040 """
1041 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1042 ``bytes`` instance and uses the certificates within for verification
1043 purposes.
1044 """
1045 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001046 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001047 )
1048
1049
1050 def test_load_verify_directory_unicode_capath(self):
1051 """
1052 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1053 ``unicode`` instance and uses the certificates within for verification
1054 purposes.
1055 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001056 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001057 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001058 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001059
1060
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001061 def test_load_verify_locations_wrong_args(self):
1062 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001063 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if called with
1064 the wrong number of arguments or with non-:py:obj:`str` arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001065 """
1066 context = Context(TLSv1_METHOD)
1067 self.assertRaises(TypeError, context.load_verify_locations)
1068 self.assertRaises(TypeError, context.load_verify_locations, object())
1069 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
1070 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
1071
1072
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001073 if platform == "win32":
1074 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001075 "See LP#404343 and LP#404344."
1076 else:
1077 def test_set_default_verify_paths(self):
1078 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001079 :py:obj:`Context.set_default_verify_paths` causes the platform-specific CA
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001080 certificate locations to be used for verification purposes.
1081 """
1082 # Testing this requires a server with a certificate signed by one of
1083 # the CAs in the platform CA location. Getting one of those costs
1084 # money. Fortunately (or unfortunately, depending on your
1085 # perspective), it's easy to think of a public server on the
1086 # internet which has such a certificate. Connecting to the network
1087 # in a unit test is bad, but it's the only way I can think of to
1088 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001089
Alex Gaynorb586da32014-11-15 09:22:21 -08001090 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
1091 context = Context(TLSv1_METHOD)
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001092 context.set_default_verify_paths()
1093 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02001094 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001095 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001096
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001097 client = socket()
1098 client.connect(('verisign.com', 443))
1099 clientSSL = Connection(context, client)
1100 clientSSL.set_connect_state()
1101 clientSSL.do_handshake()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001102 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001103 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001104
1105
1106 def test_set_default_verify_paths_signature(self):
1107 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001108 :py:obj:`Context.set_default_verify_paths` takes no arguments and raises
1109 :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001110 """
1111 context = Context(TLSv1_METHOD)
1112 self.assertRaises(TypeError, context.set_default_verify_paths, None)
1113 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
1114 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001115
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001116
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001117 def test_add_extra_chain_cert_invalid_cert(self):
1118 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001119 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if called with
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001120 other than one argument or if called with an object which is not an
Jonathan Ballet648875f2011-07-16 14:14:58 +09001121 instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001122 """
1123 context = Context(TLSv1_METHOD)
1124 self.assertRaises(TypeError, context.add_extra_chain_cert)
1125 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
1126 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
1127
1128
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001129 def _handshake_test(self, serverContext, clientContext):
1130 """
1131 Verify that a client and server created with the given contexts can
1132 successfully handshake and communicate.
1133 """
1134 serverSocket, clientSocket = socket_pair()
1135
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001136 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001137 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001138
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001139 client = Connection(clientContext, clientSocket)
1140 client.set_connect_state()
1141
1142 # Make them talk to each other.
1143 # self._interactInMemory(client, server)
1144 for i in range(3):
1145 for s in [client, server]:
1146 try:
1147 s.do_handshake()
1148 except WantReadError:
1149 pass
1150
1151
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001152 def test_set_verify_callback_connection_argument(self):
1153 """
1154 The first argument passed to the verify callback is the
1155 :py:class:`Connection` instance for which verification is taking place.
1156 """
1157 serverContext = Context(TLSv1_METHOD)
1158 serverContext.use_privatekey(
1159 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1160 serverContext.use_certificate(
1161 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1162 serverConnection = Connection(serverContext, None)
1163
1164 class VerifyCallback(object):
1165 def callback(self, connection, *args):
1166 self.connection = connection
1167 return 1
1168
1169 verify = VerifyCallback()
1170 clientContext = Context(TLSv1_METHOD)
1171 clientContext.set_verify(VERIFY_PEER, verify.callback)
1172 clientConnection = Connection(clientContext, None)
1173 clientConnection.set_connect_state()
1174
1175 self._handshakeInMemory(clientConnection, serverConnection)
1176
1177 self.assertIdentical(verify.connection, clientConnection)
1178
1179
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001180 def test_set_verify_callback_exception(self):
1181 """
1182 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1183 exception, verification fails and the exception is propagated to the
1184 caller of :py:obj:`Connection.do_handshake`.
1185 """
1186 serverContext = Context(TLSv1_METHOD)
1187 serverContext.use_privatekey(
1188 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1189 serverContext.use_certificate(
1190 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1191
1192 clientContext = Context(TLSv1_METHOD)
1193 def verify_callback(*args):
1194 raise Exception("silly verify failure")
1195 clientContext.set_verify(VERIFY_PEER, verify_callback)
1196
1197 exc = self.assertRaises(
1198 Exception, self._handshake_test, serverContext, clientContext)
1199 self.assertEqual("silly verify failure", str(exc))
1200
1201
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001202 def test_add_extra_chain_cert(self):
1203 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001204 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509`
1205 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001206
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001207 See :py:obj:`_create_certificate_chain` for the details of the
1208 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001209
1210 The chain is tested by starting a server with scert and connecting
1211 to it with a client which trusts cacert and requires verification to
1212 succeed.
1213 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001214 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001215 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1216
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001217 # Dump the CA certificate to a file because that's the only way to load
1218 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001219 for cert, name in [(cacert, 'ca.pem'),
1220 (icert, 'i.pem'),
1221 (scert, 's.pem')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001222 with open(join(self.tmpdir, name), 'w') as f:
1223 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001224
Hynek Schlawack1902c012015-04-16 15:06:41 -04001225 for key, name in [(cakey, 'ca.key'),
1226 (ikey, 'i.key'),
1227 (skey, 's.key')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001228 with open(join(self.tmpdir, name), 'w') as f:
1229 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001230
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001231 # Create the server context
1232 serverContext = Context(TLSv1_METHOD)
1233 serverContext.use_privatekey(skey)
1234 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001235 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001236 serverContext.add_extra_chain_cert(icert)
1237
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001238 # Create the client
1239 clientContext = Context(TLSv1_METHOD)
1240 clientContext.set_verify(
1241 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001242 clientContext.load_verify_locations(join(self.tmpdir, "ca.pem"))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001243
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001244 # Try it out.
1245 self._handshake_test(serverContext, clientContext)
1246
1247
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001248 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001249 """
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001250 Verify that :py:obj:`Context.use_certificate_chain_file` reads a
1251 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001252
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001253 The chain is tested by starting a server with scert and connecting to
1254 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001255 succeed.
1256 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001257 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001258 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1259
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001260 makedirs(certdir)
1261
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001262 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1263 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001264
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001265 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001266 with open(chainFile, 'wb') as fObj:
1267 # Most specific to least general.
1268 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1269 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1270 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1271
1272 with open(caFile, 'w') as fObj:
1273 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001274
1275 serverContext = Context(TLSv1_METHOD)
1276 serverContext.use_certificate_chain_file(chainFile)
1277 serverContext.use_privatekey(skey)
1278
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001279 clientContext = Context(TLSv1_METHOD)
1280 clientContext.set_verify(
1281 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001282 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001283
1284 self._handshake_test(serverContext, clientContext)
1285
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001286
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001287 def test_use_certificate_chain_file_bytes(self):
1288 """
1289 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1290 an instance of ``bytes``) to specify additional certificates to use to
1291 construct and verify a trust chain.
1292 """
1293 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001294 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001295 )
1296
1297
1298 def test_use_certificate_chain_file_unicode(self):
1299 """
1300 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1301 an instance of ``unicode``) to specify additional certificates to use
1302 to construct and verify a trust chain.
1303 """
1304 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001305 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001306 )
1307
1308
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001309 def test_use_certificate_chain_file_wrong_args(self):
1310 """
1311 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1312 if passed zero or more than one argument or when passed a non-byte
1313 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error` when
1314 passed a bad chain file name (for example, the name of a file which does
1315 not exist).
1316 """
1317 context = Context(TLSv1_METHOD)
1318 self.assertRaises(TypeError, context.use_certificate_chain_file)
1319 self.assertRaises(TypeError, context.use_certificate_chain_file, object())
1320 self.assertRaises(TypeError, context.use_certificate_chain_file, b"foo", object())
1321
1322 self.assertRaises(Error, context.use_certificate_chain_file, self.mktemp())
1323
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001324 # XXX load_client_ca
1325 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001326
1327 def test_get_verify_mode_wrong_args(self):
1328 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001329 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001330 arguments.
1331 """
1332 context = Context(TLSv1_METHOD)
1333 self.assertRaises(TypeError, context.get_verify_mode, None)
1334
1335
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001336 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001337 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001338 :py:obj:`Context.get_verify_mode` returns the verify mode flags previously
1339 passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001340 """
1341 context = Context(TLSv1_METHOD)
1342 self.assertEquals(context.get_verify_mode(), 0)
1343 context.set_verify(
1344 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1345 self.assertEquals(
1346 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1347
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001348
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001349 if not PY3:
1350 def test_set_verify_mode_long(self):
1351 """
1352 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1353 type :py:obj:`long` as well as :py:obj:`int`.
1354 """
1355 context = Context(TLSv1_METHOD)
1356 self.assertEquals(context.get_verify_mode(), 0)
1357 context.set_verify(
1358 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None)
1359 self.assertEquals(
1360 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1361
1362
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001363 def test_load_tmp_dh_wrong_args(self):
1364 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001365 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
1366 number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001367 """
1368 context = Context(TLSv1_METHOD)
1369 self.assertRaises(TypeError, context.load_tmp_dh)
1370 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1371 self.assertRaises(TypeError, context.load_tmp_dh, object())
1372
1373
1374 def test_load_tmp_dh_missing_file(self):
1375 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001376 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the specified file
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001377 does not exist.
1378 """
1379 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001380 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001381
1382
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001383 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001384 """
1385 Verify that calling ``Context.load_tmp_dh`` with the given filename
1386 does not raise an exception.
1387 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001388 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001389 with open(dhfilename, "w") as dhfile:
1390 dhfile.write(dhparam)
1391
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001392 context.load_tmp_dh(dhfilename)
1393 # XXX What should I assert here? -exarkun
1394
1395
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001396 def test_load_tmp_dh_bytes(self):
1397 """
1398 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1399 specified file (given as ``bytes``).
1400 """
1401 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001402 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001403 )
1404
1405
1406 def test_load_tmp_dh_unicode(self):
1407 """
1408 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1409 specified file (given as ``unicode``).
1410 """
1411 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001412 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001413 )
1414
1415
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001416 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001417 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001418 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001419 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001420 """
1421 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001422 for curve in get_elliptic_curves():
1423 # The only easily "assertable" thing is that it does not raise an
1424 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001425 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001426
1427
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001428 def test_set_cipher_list_bytes(self):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001429 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001430 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
1431 ciphers which connections created with the context object will be able
1432 to choose from.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001433 """
1434 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001435 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001436 conn = Connection(context, None)
1437 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001438
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001439
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001440 def test_set_cipher_list_text(self):
1441 """
1442 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
1443 the ciphers which connections created with the context object will be
1444 able to choose from.
1445 """
1446 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -05001447 context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001448 conn = Connection(context, None)
1449 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
1450
1451
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001452 def test_set_cipher_list_wrong_args(self):
1453 """
Jean-Paul Calderone17044832014-01-18 10:20:11 -05001454 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
1455 passed zero arguments or more than one argument or when passed a
1456 non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001457 passed an incorrect cipher list string.
1458 """
1459 context = Context(TLSv1_METHOD)
1460 self.assertRaises(TypeError, context.set_cipher_list)
1461 self.assertRaises(TypeError, context.set_cipher_list, object())
1462 self.assertRaises(TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object())
1463
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001464 self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001465
1466
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001467 def test_set_session_cache_mode_wrong_args(self):
1468 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001469 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1470 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001471 """
1472 context = Context(TLSv1_METHOD)
1473 self.assertRaises(TypeError, context.set_session_cache_mode)
1474 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1475
1476
1477 def test_get_session_cache_mode_wrong_args(self):
1478 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001479 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1480 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001481 """
1482 context = Context(TLSv1_METHOD)
1483 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1484
1485
1486 def test_session_cache_mode(self):
1487 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001488 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1489 cached. The setting can be retrieved via
1490 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001491 """
1492 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001493 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001494 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1495 self.assertEqual(SESS_CACHE_OFF, off)
1496 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1497
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001498 if not PY3:
1499 def test_session_cache_mode_long(self):
1500 """
1501 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1502 of type :py:obj:`long` as well as :py:obj:`int`.
1503 """
1504 context = Context(TLSv1_METHOD)
1505 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1506 self.assertEqual(
1507 SESS_CACHE_BOTH, context.get_session_cache_mode())
1508
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001509
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001510 def test_get_cert_store(self):
1511 """
1512 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store` instance.
1513 """
1514 context = Context(TLSv1_METHOD)
1515 store = context.get_cert_store()
1516 self.assertIsInstance(store, X509Store)
1517
1518
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001519
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001520class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1521 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001522 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
1523 :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001524 """
1525 def test_wrong_args(self):
1526 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001527 :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001528 with other than one argument.
1529 """
1530 context = Context(TLSv1_METHOD)
1531 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1532 self.assertRaises(
1533 TypeError, context.set_tlsext_servername_callback, 1, 2)
1534
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001535
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001536 def test_old_callback_forgotten(self):
1537 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001538 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001539 callback, the one it replaces is dereferenced.
1540 """
1541 def callback(connection):
1542 pass
1543
1544 def replacement(connection):
1545 pass
1546
1547 context = Context(TLSv1_METHOD)
1548 context.set_tlsext_servername_callback(callback)
1549
1550 tracker = ref(callback)
1551 del callback
1552
1553 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001554
1555 # One run of the garbage collector happens to work on CPython. PyPy
1556 # doesn't collect the underlying object until a second run for whatever
1557 # reason. That's fine, it still demonstrates our code has properly
1558 # dropped the reference.
1559 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001560 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001561
1562 callback = tracker()
1563 if callback is not None:
1564 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001565 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001566 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001567
1568
1569 def test_no_servername(self):
1570 """
1571 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001572 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
1573 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001574 """
1575 args = []
1576 def servername(conn):
1577 args.append((conn, conn.get_servername()))
1578 context = Context(TLSv1_METHOD)
1579 context.set_tlsext_servername_callback(servername)
1580
1581 # Lose our reference to it. The Context is responsible for keeping it
1582 # alive now.
1583 del servername
1584 collect()
1585
1586 # Necessary to actually accept the connection
1587 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1588 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1589
1590 # Do a little connection to trigger the logic
1591 server = Connection(context, None)
1592 server.set_accept_state()
1593
1594 client = Connection(Context(TLSv1_METHOD), None)
1595 client.set_connect_state()
1596
1597 self._interactInMemory(server, client)
1598
1599 self.assertEqual([(server, None)], args)
1600
1601
1602 def test_servername(self):
1603 """
1604 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +09001605 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
1606 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001607 """
1608 args = []
1609 def servername(conn):
1610 args.append((conn, conn.get_servername()))
1611 context = Context(TLSv1_METHOD)
1612 context.set_tlsext_servername_callback(servername)
1613
1614 # Necessary to actually accept the connection
1615 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1616 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1617
1618 # Do a little connection to trigger the logic
1619 server = Connection(context, None)
1620 server.set_accept_state()
1621
1622 client = Connection(Context(TLSv1_METHOD), None)
1623 client.set_connect_state()
1624 client.set_tlsext_host_name(b("foo1.example.com"))
1625
1626 self._interactInMemory(server, client)
1627
1628 self.assertEqual([(server, b("foo1.example.com"))], args)
1629
1630
Cory Benfield84a121e2014-03-31 20:30:25 +01001631class NextProtoNegotiationTests(TestCase, _LoopbackMixin):
1632 """
1633 Test for Next Protocol Negotiation in PyOpenSSL.
1634 """
Cory Benfieldba1820d2015-04-13 17:39:12 -04001635 if _lib.Cryptography_HAS_NEXTPROTONEG:
1636 def test_npn_success(self):
1637 """
1638 Tests that clients and servers that agree on the negotiated next
1639 protocol can correct establish a connection, and that the agreed
1640 protocol is reported by the connections.
1641 """
1642 advertise_args = []
1643 select_args = []
1644 def advertise(conn):
1645 advertise_args.append((conn,))
1646 return [b'http/1.1', b'spdy/2']
1647 def select(conn, options):
1648 select_args.append((conn, options))
1649 return b'spdy/2'
Cory Benfield84a121e2014-03-31 20:30:25 +01001650
Cory Benfieldba1820d2015-04-13 17:39:12 -04001651 server_context = Context(TLSv1_METHOD)
1652 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001653
Cory Benfieldba1820d2015-04-13 17:39:12 -04001654 client_context = Context(TLSv1_METHOD)
1655 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001656
Cory Benfieldba1820d2015-04-13 17:39:12 -04001657 # Necessary to actually accept the connection
1658 server_context.use_privatekey(
1659 load_privatekey(FILETYPE_PEM, server_key_pem))
1660 server_context.use_certificate(
1661 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001662
Cory Benfieldba1820d2015-04-13 17:39:12 -04001663 # Do a little connection to trigger the logic
1664 server = Connection(server_context, None)
1665 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001666
Cory Benfieldba1820d2015-04-13 17:39:12 -04001667 client = Connection(client_context, None)
1668 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001669
Cory Benfieldba1820d2015-04-13 17:39:12 -04001670 self._interactInMemory(server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001671
Cory Benfieldba1820d2015-04-13 17:39:12 -04001672 self.assertEqual([(server,)], advertise_args)
1673 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001674
Cory Benfieldba1820d2015-04-13 17:39:12 -04001675 self.assertEqual(server.get_next_proto_negotiated(), b'spdy/2')
1676 self.assertEqual(client.get_next_proto_negotiated(), b'spdy/2')
Cory Benfield84a121e2014-03-31 20:30:25 +01001677
1678
Cory Benfieldba1820d2015-04-13 17:39:12 -04001679 def test_npn_client_fail(self):
1680 """
1681 Tests that when clients and servers cannot agree on what protocol
1682 to use next that the TLS connection does not get established.
1683 """
1684 advertise_args = []
1685 select_args = []
1686 def advertise(conn):
1687 advertise_args.append((conn,))
1688 return [b'http/1.1', b'spdy/2']
1689 def select(conn, options):
1690 select_args.append((conn, options))
1691 return b''
Cory Benfield84a121e2014-03-31 20:30:25 +01001692
Cory Benfieldba1820d2015-04-13 17:39:12 -04001693 server_context = Context(TLSv1_METHOD)
1694 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001695
Cory Benfieldba1820d2015-04-13 17:39:12 -04001696 client_context = Context(TLSv1_METHOD)
1697 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001698
Cory Benfieldba1820d2015-04-13 17:39:12 -04001699 # Necessary to actually accept the connection
1700 server_context.use_privatekey(
1701 load_privatekey(FILETYPE_PEM, server_key_pem))
1702 server_context.use_certificate(
1703 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001704
Cory Benfieldba1820d2015-04-13 17:39:12 -04001705 # Do a little connection to trigger the logic
1706 server = Connection(server_context, None)
1707 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001708
Cory Benfieldba1820d2015-04-13 17:39:12 -04001709 client = Connection(client_context, None)
1710 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001711
Cory Benfieldba1820d2015-04-13 17:39:12 -04001712 # If the client doesn't return anything, the connection will fail.
1713 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001714
Cory Benfieldba1820d2015-04-13 17:39:12 -04001715 self.assertEqual([(server,)], advertise_args)
1716 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001717
1718
Cory Benfieldba1820d2015-04-13 17:39:12 -04001719 def test_npn_select_error(self):
1720 """
1721 Test that we can handle exceptions in the select callback. If
1722 select fails it should be fatal to the connection.
1723 """
1724 advertise_args = []
1725 def advertise(conn):
1726 advertise_args.append((conn,))
1727 return [b'http/1.1', b'spdy/2']
1728 def select(conn, options):
1729 raise TypeError
Cory Benfield0ea76e72015-03-22 09:05:28 +00001730
Cory Benfieldba1820d2015-04-13 17:39:12 -04001731 server_context = Context(TLSv1_METHOD)
1732 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001733
Cory Benfieldba1820d2015-04-13 17:39:12 -04001734 client_context = Context(TLSv1_METHOD)
1735 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001736
Cory Benfieldba1820d2015-04-13 17:39:12 -04001737 # Necessary to actually accept the connection
1738 server_context.use_privatekey(
1739 load_privatekey(FILETYPE_PEM, server_key_pem))
1740 server_context.use_certificate(
1741 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001742
Cory Benfieldba1820d2015-04-13 17:39:12 -04001743 # Do a little connection to trigger the logic
1744 server = Connection(server_context, None)
1745 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001746
Cory Benfieldba1820d2015-04-13 17:39:12 -04001747 client = Connection(client_context, None)
1748 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001749
Cory Benfieldba1820d2015-04-13 17:39:12 -04001750 # If the callback throws an exception it should be raised here.
1751 self.assertRaises(
1752 TypeError, self._interactInMemory, server, client
1753 )
1754 self.assertEqual([(server,)], advertise_args)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001755
1756
Cory Benfieldba1820d2015-04-13 17:39:12 -04001757 def test_npn_advertise_error(self):
1758 """
1759 Test that we can handle exceptions in the advertise callback. If
1760 advertise fails no NPN is advertised to the client.
1761 """
1762 select_args = []
1763 def advertise(conn):
1764 raise TypeError
1765 def select(conn, options):
1766 select_args.append((conn, options))
1767 return b''
Cory Benfield0ea76e72015-03-22 09:05:28 +00001768
Cory Benfieldba1820d2015-04-13 17:39:12 -04001769 server_context = Context(TLSv1_METHOD)
1770 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001771
Cory Benfieldba1820d2015-04-13 17:39:12 -04001772 client_context = Context(TLSv1_METHOD)
1773 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001774
Cory Benfieldba1820d2015-04-13 17:39:12 -04001775 # Necessary to actually accept the connection
1776 server_context.use_privatekey(
1777 load_privatekey(FILETYPE_PEM, server_key_pem))
1778 server_context.use_certificate(
1779 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001780
Cory Benfieldba1820d2015-04-13 17:39:12 -04001781 # Do a little connection to trigger the logic
1782 server = Connection(server_context, None)
1783 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001784
Cory Benfieldba1820d2015-04-13 17:39:12 -04001785 client = Connection(client_context, None)
1786 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001787
Cory Benfieldba1820d2015-04-13 17:39:12 -04001788 # If the client doesn't return anything, the connection will fail.
1789 self.assertRaises(
1790 TypeError, self._interactInMemory, server, client
1791 )
1792 self.assertEqual([], select_args)
1793
1794 else:
1795 # No NPN.
1796 def test_npn_not_implemented(self):
1797 # Test the context methods first.
1798 context = Context(TLSv1_METHOD)
1799 fail_methods = [
1800 context.set_npn_advertise_callback,
1801 context.set_npn_select_callback,
1802 ]
1803 for method in fail_methods:
1804 self.assertRaises(
1805 NotImplementedError, method, None
1806 )
1807
1808 # Now test a connection.
1809 conn = Connection(context)
1810 fail_methods = [
1811 conn.get_next_proto_negotiated,
1812 ]
1813 for method in fail_methods:
1814 self.assertRaises(NotImplementedError, method)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001815
1816
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001817
Cory Benfield12eae892014-06-07 15:42:56 +01001818class ApplicationLayerProtoNegotiationTests(TestCase, _LoopbackMixin):
1819 """
1820 Tests for ALPN in PyOpenSSL.
1821 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001822 # Skip tests on versions that don't support ALPN.
1823 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001824
Cory Benfielde46fa842015-04-13 16:50:49 -04001825 def test_alpn_success(self):
1826 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001827 Clients and servers that agree on the negotiated ALPN protocol can
1828 correct establish a connection, and the agreed protocol is reported
1829 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001830 """
1831 select_args = []
1832 def select(conn, options):
1833 select_args.append((conn, options))
1834 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001835
Cory Benfielde46fa842015-04-13 16:50:49 -04001836 client_context = Context(TLSv1_METHOD)
1837 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001838
Cory Benfielde46fa842015-04-13 16:50:49 -04001839 server_context = Context(TLSv1_METHOD)
1840 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001841
Cory Benfielde46fa842015-04-13 16:50:49 -04001842 # Necessary to actually accept the connection
1843 server_context.use_privatekey(
1844 load_privatekey(FILETYPE_PEM, server_key_pem))
1845 server_context.use_certificate(
1846 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001847
Cory Benfielde46fa842015-04-13 16:50:49 -04001848 # Do a little connection to trigger the logic
1849 server = Connection(server_context, None)
1850 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001851
Cory Benfielde46fa842015-04-13 16:50:49 -04001852 client = Connection(client_context, None)
1853 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001854
Cory Benfielde46fa842015-04-13 16:50:49 -04001855 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001856
Cory Benfielde46fa842015-04-13 16:50:49 -04001857 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
1858
1859 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1860 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001861
1862
Cory Benfielde46fa842015-04-13 16:50:49 -04001863 def test_alpn_set_on_connection(self):
1864 """
1865 The same as test_alpn_success, but setting the ALPN protocols on
1866 the connection rather than the context.
1867 """
1868 select_args = []
1869 def select(conn, options):
1870 select_args.append((conn, options))
1871 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001872
Cory Benfielde46fa842015-04-13 16:50:49 -04001873 # Setup the client context but don't set any ALPN protocols.
1874 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001875
Cory Benfielde46fa842015-04-13 16:50:49 -04001876 server_context = Context(TLSv1_METHOD)
1877 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001878
Cory Benfielde46fa842015-04-13 16:50:49 -04001879 # Necessary to actually accept the connection
1880 server_context.use_privatekey(
1881 load_privatekey(FILETYPE_PEM, server_key_pem))
1882 server_context.use_certificate(
1883 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001884
Cory Benfielde46fa842015-04-13 16:50:49 -04001885 # Do a little connection to trigger the logic
1886 server = Connection(server_context, None)
1887 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001888
Cory Benfielde46fa842015-04-13 16:50:49 -04001889 # Set the ALPN protocols on the client connection.
1890 client = Connection(client_context, None)
1891 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1892 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001893
Cory Benfielde46fa842015-04-13 16:50:49 -04001894 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001895
Cory Benfielde46fa842015-04-13 16:50:49 -04001896 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001897
Cory Benfielde46fa842015-04-13 16:50:49 -04001898 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1899 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001900
1901
Cory Benfielde46fa842015-04-13 16:50:49 -04001902 def test_alpn_server_fail(self):
1903 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001904 When clients and servers cannot agree on what protocol to use next
1905 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001906 """
1907 select_args = []
1908 def select(conn, options):
1909 select_args.append((conn, options))
1910 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001911
Cory Benfielde46fa842015-04-13 16:50:49 -04001912 client_context = Context(TLSv1_METHOD)
1913 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001914
Cory Benfielde46fa842015-04-13 16:50:49 -04001915 server_context = Context(TLSv1_METHOD)
1916 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001917
Cory Benfielde46fa842015-04-13 16:50:49 -04001918 # Necessary to actually accept the connection
1919 server_context.use_privatekey(
1920 load_privatekey(FILETYPE_PEM, server_key_pem))
1921 server_context.use_certificate(
1922 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001923
Cory Benfielde46fa842015-04-13 16:50:49 -04001924 # Do a little connection to trigger the logic
1925 server = Connection(server_context, None)
1926 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001927
Cory Benfielde46fa842015-04-13 16:50:49 -04001928 client = Connection(client_context, None)
1929 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001930
Cory Benfielde46fa842015-04-13 16:50:49 -04001931 # If the client doesn't return anything, the connection will fail.
1932 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001933
Cory Benfielde46fa842015-04-13 16:50:49 -04001934 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001935
1936
Cory Benfielde46fa842015-04-13 16:50:49 -04001937 def test_alpn_no_server(self):
1938 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001939 When clients and servers cannot agree on what protocol to use next
1940 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04001941 """
1942 client_context = Context(TLSv1_METHOD)
1943 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04001944
Cory Benfielde46fa842015-04-13 16:50:49 -04001945 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04001946
Cory Benfielde46fa842015-04-13 16:50:49 -04001947 # Necessary to actually accept the connection
1948 server_context.use_privatekey(
1949 load_privatekey(FILETYPE_PEM, server_key_pem))
1950 server_context.use_certificate(
1951 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04001952
Cory Benfielde46fa842015-04-13 16:50:49 -04001953 # Do a little connection to trigger the logic
1954 server = Connection(server_context, None)
1955 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001956
Cory Benfielde46fa842015-04-13 16:50:49 -04001957 client = Connection(client_context, None)
1958 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001959
Cory Benfielde46fa842015-04-13 16:50:49 -04001960 # Do the dance.
1961 self._interactInMemory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04001962
Cory Benfielde46fa842015-04-13 16:50:49 -04001963 self.assertEqual(client.get_alpn_proto_negotiated(), b'')
Cory Benfielde3d57152015-04-11 17:57:35 -04001964
1965
Cory Benfielde46fa842015-04-13 16:50:49 -04001966 def test_alpn_callback_exception(self):
1967 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001968 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04001969 """
1970 select_args = []
1971 def select(conn, options):
1972 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04001973 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001974
Cory Benfielde46fa842015-04-13 16:50:49 -04001975 client_context = Context(TLSv1_METHOD)
1976 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04001977
Cory Benfielde46fa842015-04-13 16:50:49 -04001978 server_context = Context(TLSv1_METHOD)
1979 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04001980
Cory Benfielde46fa842015-04-13 16:50:49 -04001981 # Necessary to actually accept the connection
1982 server_context.use_privatekey(
1983 load_privatekey(FILETYPE_PEM, server_key_pem))
1984 server_context.use_certificate(
1985 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04001986
Cory Benfielde46fa842015-04-13 16:50:49 -04001987 # Do a little connection to trigger the logic
1988 server = Connection(server_context, None)
1989 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001990
Cory Benfielde46fa842015-04-13 16:50:49 -04001991 client = Connection(client_context, None)
1992 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001993
Cory Benfielde46fa842015-04-13 16:50:49 -04001994 self.assertRaises(
1995 TypeError, self._interactInMemory, server, client
1996 )
1997 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfieldf1177e72015-04-12 09:11:49 -04001998
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001999 else:
2000 # No ALPN.
2001 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04002002 """
2003 If ALPN is not in OpenSSL, we should raise NotImplementedError.
2004 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002005 # Test the context methods first.
2006 context = Context(TLSv1_METHOD)
Cory Benfield307e9e62015-04-13 18:21:12 -04002007 self.assertRaises(
2008 NotImplementedError, context.set_alpn_protos, None
2009 )
2010 self.assertRaises(
2011 NotImplementedError, context.set_alpn_select_callback, None
2012 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002013
2014 # Now test a connection.
2015 conn = Connection(context)
Cory Benfield307e9e62015-04-13 18:21:12 -04002016 self.assertRaises(
Alex Gaynor68417232015-09-04 07:56:29 -04002017 NotImplementedError, conn.set_alpn_protos, None
Cory Benfield307e9e62015-04-13 18:21:12 -04002018 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002019
Cory Benfieldf1177e72015-04-12 09:11:49 -04002020
Cory Benfield12eae892014-06-07 15:42:56 +01002021
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002022class SessionTests(TestCase):
2023 """
2024 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
2025 """
2026 def test_construction(self):
2027 """
2028 :py:class:`Session` can be constructed with no arguments, creating a new
2029 instance of that type.
2030 """
2031 new_session = Session()
2032 self.assertTrue(isinstance(new_session, Session))
2033
2034
2035 def test_construction_wrong_args(self):
2036 """
2037 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
2038 is raised.
2039 """
2040 self.assertRaises(TypeError, Session, 123)
2041 self.assertRaises(TypeError, Session, "hello")
2042 self.assertRaises(TypeError, Session, object())
2043
2044
2045
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002046class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05002047 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002048 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002049 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002050 # XXX get_peer_certificate -> None
2051 # XXX sock_shutdown
2052 # XXX master_key -> TypeError
2053 # XXX server_random -> TypeError
2054 # XXX state_string
2055 # XXX connect -> TypeError
2056 # XXX connect_ex -> TypeError
2057 # XXX set_connect_state -> TypeError
2058 # XXX set_accept_state -> TypeError
2059 # XXX renegotiate_pending
2060 # XXX do_handshake -> TypeError
2061 # XXX bio_read -> TypeError
2062 # XXX recv -> TypeError
2063 # XXX send -> TypeError
2064 # XXX bio_write -> TypeError
2065
Rick Deane15b1472009-07-09 15:53:42 -05002066 def test_type(self):
2067 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002068 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002069 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002070 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002071 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05002072 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002073 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002074
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002075
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002076 def test_get_context(self):
2077 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002078 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
2079 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002080 """
2081 context = Context(TLSv1_METHOD)
2082 connection = Connection(context, None)
2083 self.assertIdentical(connection.get_context(), context)
2084
2085
2086 def test_get_context_wrong_args(self):
2087 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002088 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002089 arguments.
2090 """
2091 connection = Connection(Context(TLSv1_METHOD), None)
2092 self.assertRaises(TypeError, connection.get_context, None)
2093
2094
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002095 def test_set_context_wrong_args(self):
2096 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002097 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
2098 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002099 than 1.
2100 """
2101 ctx = Context(TLSv1_METHOD)
2102 connection = Connection(ctx, None)
2103 self.assertRaises(TypeError, connection.set_context)
2104 self.assertRaises(TypeError, connection.set_context, object())
2105 self.assertRaises(TypeError, connection.set_context, "hello")
2106 self.assertRaises(TypeError, connection.set_context, 1)
2107 self.assertRaises(TypeError, connection.set_context, 1, 2)
2108 self.assertRaises(
2109 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
2110 self.assertIdentical(ctx, connection.get_context())
2111
2112
2113 def test_set_context(self):
2114 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002115 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002116 for the connection.
2117 """
2118 original = Context(SSLv23_METHOD)
2119 replacement = Context(TLSv1_METHOD)
2120 connection = Connection(original, None)
2121 connection.set_context(replacement)
2122 self.assertIdentical(replacement, connection.get_context())
2123 # Lose our references to the contexts, just in case the Connection isn't
2124 # properly managing its own contributions to their reference counts.
2125 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002126 collect()
2127
2128
2129 def test_set_tlsext_host_name_wrong_args(self):
2130 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002131 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002132 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09002133 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002134 """
2135 conn = Connection(Context(TLSv1_METHOD), None)
2136 self.assertRaises(TypeError, conn.set_tlsext_host_name)
2137 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
2138 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
2139 self.assertRaises(
2140 TypeError, conn.set_tlsext_host_name, b("with\0null"))
2141
Abraham Martinc5484ba2015-03-25 15:33:05 +00002142 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002143 # On Python 3.x, don't accidentally implicitly convert from text.
2144 self.assertRaises(
2145 TypeError,
2146 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002147
2148
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002149 def test_get_servername_wrong_args(self):
2150 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002151 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002152 arguments.
2153 """
2154 connection = Connection(Context(TLSv1_METHOD), None)
2155 self.assertRaises(TypeError, connection.get_servername, object())
2156 self.assertRaises(TypeError, connection.get_servername, 1)
2157 self.assertRaises(TypeError, connection.get_servername, "hello")
2158
2159
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002160 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002161 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002162 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002163 immediate read.
2164 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002165 connection = Connection(Context(TLSv1_METHOD), None)
2166 self.assertEquals(connection.pending(), 0)
2167
2168
2169 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002170 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002171 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002172 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002173 connection = Connection(Context(TLSv1_METHOD), None)
2174 self.assertRaises(TypeError, connection.pending, None)
2175
2176
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002177 def test_peek(self):
2178 """
2179 :py:obj:`Connection.recv` peeks into the connection if :py:obj:`socket.MSG_PEEK` is passed.
2180 """
2181 server, client = self._loopback()
2182 server.send(b('xy'))
2183 self.assertEqual(client.recv(2, MSG_PEEK), b('xy'))
2184 self.assertEqual(client.recv(2, MSG_PEEK), b('xy'))
2185 self.assertEqual(client.recv(2), b('xy'))
2186
2187
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002188 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002189 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002190 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002191 argument or with the wrong number of arguments.
2192 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002193 connection = Connection(Context(TLSv1_METHOD), socket())
2194 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002195 self.assertRaises(TypeError, connection.connect)
2196 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002197
kjavfe508d62015-09-02 12:20:35 +01002198 def test_connection_undefined_attr(self):
2199 """
2200 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
2201 argument or with the wrong number of arguments.
2202 """
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002203
kjavfe508d62015-09-02 12:20:35 +01002204 def attr_access_test(connection):
2205 return connection.an_attribute_which_is_not_defined
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002206
kjavfe508d62015-09-02 12:20:35 +01002207 connection = Connection(Context(TLSv1_METHOD), None)
2208 self.assertRaises(AttributeError, attr_access_test, connection)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002209
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002210 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002211 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002212 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002213 connect method raises it.
2214 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002215 client = socket()
2216 context = Context(TLSv1_METHOD)
2217 clientSSL = Connection(context, client)
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002218 with pytest.raises(error) as exc:
2219 clientSSL.connect(("127.0.0.1", 1))
2220 assert exc.value.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002221
2222 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002223 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002224 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002225 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002226 port = socket()
2227 port.bind(('', 0))
2228 port.listen(3)
2229
2230 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002231 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2232 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002233
2234
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002235 if platform == "darwin":
2236 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2237 else:
2238 def test_connect_ex(self):
2239 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002240 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002241 errno instead of raising an exception.
2242 """
2243 port = socket()
2244 port.bind(('', 0))
2245 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002246
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002247 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2248 clientSSL.setblocking(False)
2249 result = clientSSL.connect_ex(port.getsockname())
2250 expected = (EINPROGRESS, EWOULDBLOCK)
2251 self.assertTrue(
2252 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002253
2254
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002255 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002256 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002257 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002258 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002259 connection = Connection(Context(TLSv1_METHOD), socket())
2260 self.assertRaises(TypeError, connection.accept, None)
2261
2262
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002263 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002264 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002265 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
2266 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002267 connection originated from.
2268 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002269 ctx = Context(TLSv1_METHOD)
2270 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2271 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002272 port = socket()
2273 portSSL = Connection(ctx, port)
2274 portSSL.bind(('', 0))
2275 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002276
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002277 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002278
2279 # Calling portSSL.getsockname() here to get the server IP address sounds
2280 # great, but frequently fails on Windows.
2281 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002282
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002283 serverSSL, address = portSSL.accept()
2284
2285 self.assertTrue(isinstance(serverSSL, Connection))
2286 self.assertIdentical(serverSSL.get_context(), ctx)
2287 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002288
2289
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002290 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002291 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002292 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002293 number of arguments or with arguments other than integers.
2294 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002295 connection = Connection(Context(TLSv1_METHOD), None)
2296 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04002297 self.assertRaises(TypeError, connection.get_shutdown, None)
2298 self.assertRaises(TypeError, connection.set_shutdown)
2299 self.assertRaises(TypeError, connection.set_shutdown, None)
2300 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002301
2302
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002303 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002304 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002305 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002306 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002307 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002308 self.assertFalse(server.shutdown())
2309 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002310 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002311 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
2312 client.shutdown()
Alex Gaynor43307782015-09-04 09:05:45 -04002313 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002314 self.assertRaises(ZeroReturnError, server.recv, 1024)
Alex Gaynor43307782015-09-04 09:05:45 -04002315 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002316
2317
Paul Aurichc85e0862015-01-08 08:34:33 -08002318 def test_shutdown_closed(self):
2319 """
2320 If the underlying socket is closed, :py:obj:`Connection.shutdown` propagates the
2321 write error from the low level write call.
2322 """
2323 server, client = self._loopback()
2324 server.sock_shutdown(2)
2325 exc = self.assertRaises(SysCallError, server.shutdown)
2326 if platform == "win32":
2327 self.assertEqual(exc.args[0], ESHUTDOWN)
2328 else:
2329 self.assertEqual(exc.args[0], EPIPE)
2330
2331
Glyph89389472015-04-14 17:29:26 -04002332 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002333 """
Glyph89389472015-04-14 17:29:26 -04002334 If the underlying connection is truncated, :obj:`Connection.shutdown`
2335 raises an :obj:`Error`.
Glyph6064ec32015-04-14 16:38:22 -04002336 """
Glyph89389472015-04-14 17:29:26 -04002337 server_ctx = Context(TLSv1_METHOD)
2338 client_ctx = Context(TLSv1_METHOD)
2339 server_ctx.use_privatekey(
2340 load_privatekey(FILETYPE_PEM, server_key_pem))
2341 server_ctx.use_certificate(
2342 load_certificate(FILETYPE_PEM, server_cert_pem))
2343 server = Connection(server_ctx, None)
2344 client = Connection(client_ctx, None)
2345 self._handshakeInMemory(client, server)
2346 self.assertEqual(server.shutdown(), False)
2347 self.assertRaises(WantReadError, server.shutdown)
2348 server.bio_shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002349 self.assertRaises(Error, server.shutdown)
2350
2351
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002352 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002353 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002354 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002355 process.
2356 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002357 connection = Connection(Context(TLSv1_METHOD), socket())
2358 connection.set_shutdown(RECEIVED_SHUTDOWN)
2359 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2360
2361
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002362 if not PY3:
2363 def test_set_shutdown_long(self):
2364 """
2365 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
2366 of type :py:obj:`long` as well as :py:obj:`int`.
2367 """
2368 connection = Connection(Context(TLSv1_METHOD), socket())
2369 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
2370 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2371
2372
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002373 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002374 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002375 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
2376 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002377 with any arguments.
2378 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002379 conn = Connection(Context(TLSv1_METHOD), None)
2380 self.assertRaises(TypeError, conn.get_app_data, None)
2381 self.assertRaises(TypeError, conn.set_app_data)
2382 self.assertRaises(TypeError, conn.set_app_data, None, None)
2383
2384
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002385 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002386 """
2387 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002388 :py:obj:`Connection.set_app_data` and later retrieved with
2389 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002390 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002391 conn = Connection(Context(TLSv1_METHOD), None)
2392 app_data = object()
2393 conn.set_app_data(app_data)
2394 self.assertIdentical(conn.get_app_data(), app_data)
2395
2396
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002397 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002398 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002399 :py:obj:`Connection.makefile` is not implemented and calling that method raises
2400 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002401 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002402 conn = Connection(Context(TLSv1_METHOD), None)
2403 self.assertRaises(NotImplementedError, conn.makefile)
2404
2405
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002406 def test_get_peer_cert_chain_wrong_args(self):
2407 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002408 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002409 arguments.
2410 """
2411 conn = Connection(Context(TLSv1_METHOD), None)
2412 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
2413 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
2414 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
2415 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
2416
2417
2418 def test_get_peer_cert_chain(self):
2419 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002420 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002421 the connected server returned for the certification verification.
2422 """
2423 chain = _create_certificate_chain()
2424 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2425
2426 serverContext = Context(TLSv1_METHOD)
2427 serverContext.use_privatekey(skey)
2428 serverContext.use_certificate(scert)
2429 serverContext.add_extra_chain_cert(icert)
2430 serverContext.add_extra_chain_cert(cacert)
2431 server = Connection(serverContext, None)
2432 server.set_accept_state()
2433
2434 # Create the client
2435 clientContext = Context(TLSv1_METHOD)
2436 clientContext.set_verify(VERIFY_NONE, verify_cb)
2437 client = Connection(clientContext, None)
2438 client.set_connect_state()
2439
2440 self._interactInMemory(client, server)
2441
2442 chain = client.get_peer_cert_chain()
2443 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002444 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002445 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002446 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002447 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002448 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002449 "Authority Certificate", chain[2].get_subject().CN)
2450
2451
2452 def test_get_peer_cert_chain_none(self):
2453 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002454 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002455 certificate chain.
2456 """
2457 ctx = Context(TLSv1_METHOD)
2458 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2459 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2460 server = Connection(ctx, None)
2461 server.set_accept_state()
2462 client = Connection(Context(TLSv1_METHOD), None)
2463 client.set_connect_state()
2464 self._interactInMemory(client, server)
2465 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002466
2467
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002468 def test_get_session_wrong_args(self):
2469 """
2470 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
2471 with any arguments.
2472 """
2473 ctx = Context(TLSv1_METHOD)
2474 server = Connection(ctx, None)
2475 self.assertRaises(TypeError, server.get_session, 123)
2476 self.assertRaises(TypeError, server.get_session, "hello")
2477 self.assertRaises(TypeError, server.get_session, object())
2478
2479
2480 def test_get_session_unconnected(self):
2481 """
2482 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
2483 an object which has not been connected.
2484 """
2485 ctx = Context(TLSv1_METHOD)
2486 server = Connection(ctx, None)
2487 session = server.get_session()
2488 self.assertIdentical(None, session)
2489
2490
2491 def test_server_get_session(self):
2492 """
2493 On the server side of a connection, :py:obj:`Connection.get_session`
2494 returns a :py:class:`Session` instance representing the SSL session for
2495 that connection.
2496 """
2497 server, client = self._loopback()
2498 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002499 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002500
2501
2502 def test_client_get_session(self):
2503 """
2504 On the client side of a connection, :py:obj:`Connection.get_session`
2505 returns a :py:class:`Session` instance representing the SSL session for
2506 that connection.
2507 """
2508 server, client = self._loopback()
2509 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002510 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002511
2512
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002513 def test_set_session_wrong_args(self):
2514 """
2515 If called with an object that is not an instance of :py:class:`Session`,
2516 or with other than one argument, :py:obj:`Connection.set_session` raises
2517 :py:obj:`TypeError`.
2518 """
2519 ctx = Context(TLSv1_METHOD)
2520 connection = Connection(ctx, None)
2521 self.assertRaises(TypeError, connection.set_session)
2522 self.assertRaises(TypeError, connection.set_session, 123)
2523 self.assertRaises(TypeError, connection.set_session, "hello")
2524 self.assertRaises(TypeError, connection.set_session, object())
2525 self.assertRaises(
2526 TypeError, connection.set_session, Session(), Session())
2527
2528
2529 def test_client_set_session(self):
2530 """
2531 :py:obj:`Connection.set_session`, when used prior to a connection being
2532 established, accepts a :py:class:`Session` instance and causes an
2533 attempt to re-use the session it represents when the SSL handshake is
2534 performed.
2535 """
2536 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2537 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2538 ctx = Context(TLSv1_METHOD)
2539 ctx.use_privatekey(key)
2540 ctx.use_certificate(cert)
2541 ctx.set_session_id("unity-test")
2542
2543 def makeServer(socket):
2544 server = Connection(ctx, socket)
2545 server.set_accept_state()
2546 return server
2547
2548 originalServer, originalClient = self._loopback(
2549 serverFactory=makeServer)
2550 originalSession = originalClient.get_session()
2551
2552 def makeClient(socket):
2553 client = self._loopbackClientFactory(socket)
2554 client.set_session(originalSession)
2555 return client
2556 resumedServer, resumedClient = self._loopback(
2557 serverFactory=makeServer,
2558 clientFactory=makeClient)
2559
2560 # This is a proxy: in general, we have no access to any unique
2561 # identifier for the session (new enough versions of OpenSSL expose a
2562 # hash which could be usable, but "new enough" is very, very new).
2563 # Instead, exploit the fact that the master key is re-used if the
2564 # session is re-used. As long as the master key for the two connections
2565 # is the same, the session was re-used!
2566 self.assertEqual(
2567 originalServer.master_key(), resumedServer.master_key())
2568
2569
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002570 def test_set_session_wrong_method(self):
2571 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002572 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
2573 instance associated with a context using a different SSL method than the
2574 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
2575 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002576 """
2577 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2578 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2579 ctx = Context(TLSv1_METHOD)
2580 ctx.use_privatekey(key)
2581 ctx.use_certificate(cert)
2582 ctx.set_session_id("unity-test")
2583
2584 def makeServer(socket):
2585 server = Connection(ctx, socket)
2586 server.set_accept_state()
2587 return server
2588
2589 originalServer, originalClient = self._loopback(
2590 serverFactory=makeServer)
2591 originalSession = originalClient.get_session()
2592
2593 def makeClient(socket):
2594 # Intentionally use a different, incompatible method here.
2595 client = Connection(Context(SSLv3_METHOD), socket)
2596 client.set_connect_state()
2597 client.set_session(originalSession)
2598 return client
2599
2600 self.assertRaises(
2601 Error,
2602 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2603
2604
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002605 def test_wantWriteError(self):
2606 """
2607 :py:obj:`Connection` methods which generate output raise
2608 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2609 fail indicating a should-write state.
2610 """
2611 client_socket, server_socket = socket_pair()
2612 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002613 # anything. Only write a single byte at a time so we can be sure we
2614 # completely fill the buffer. Even though the socket API is allowed to
2615 # signal a short write via its return value it seems this doesn't
2616 # always happen on all platforms (FreeBSD and OS X particular) for the
2617 # very last bit of available buffer space.
2618 msg = b"x"
2619 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002620 try:
2621 client_socket.send(msg)
2622 except error as e:
2623 if e.errno == EWOULDBLOCK:
2624 break
2625 raise
2626 else:
2627 self.fail(
2628 "Failed to fill socket buffer, cannot test BIO want write")
2629
2630 ctx = Context(TLSv1_METHOD)
2631 conn = Connection(ctx, client_socket)
2632 # Client's speak first, so make it an SSL client
2633 conn.set_connect_state()
2634 self.assertRaises(WantWriteError, conn.do_handshake)
2635
2636 # XXX want_read
2637
Fedor Brunner416f4a12014-03-28 13:18:38 +01002638 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002639 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002640 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2641 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002642 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002643 ctx = Context(TLSv1_METHOD)
2644 connection = Connection(ctx, None)
2645 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002646
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002647
Fedor Brunner416f4a12014-03-28 13:18:38 +01002648 def test_get_peer_finished_before_connect(self):
2649 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002650 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2651 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002652 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002653 ctx = Context(TLSv1_METHOD)
2654 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002655 self.assertEqual(connection.get_peer_finished(), None)
2656
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002657
Fedor Brunner416f4a12014-03-28 13:18:38 +01002658 def test_get_finished(self):
2659 """
2660 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002661 message send from client, or server. Finished messages are send during
2662 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002663 """
2664
Fedor Brunner5747b932014-03-05 14:22:34 +01002665 server, client = self._loopback()
2666
2667 self.assertNotEqual(server.get_finished(), None)
2668 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002669
Jean-Paul Calderoned979f232014-03-30 11:58:00 -04002670
Fedor Brunner416f4a12014-03-28 13:18:38 +01002671 def test_get_peer_finished(self):
2672 """
2673 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002674 message received from client, or server. Finished messages are send
2675 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002676 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002677 server, client = self._loopback()
2678
2679 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002680 self.assertTrue(len(server.get_peer_finished()) > 0)
2681
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002682
Fedor Brunner416f4a12014-03-28 13:18:38 +01002683 def test_tls_finished_message_symmetry(self):
2684 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002685 The TLS Finished message send by server must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002686 received by client.
2687
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002688 The TLS Finished message send by client must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002689 received by server.
2690 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002691 server, client = self._loopback()
2692
Fedor Brunner5747b932014-03-05 14:22:34 +01002693 self.assertEqual(server.get_finished(), client.get_peer_finished())
2694 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002695
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002696
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002697 def test_get_cipher_name_before_connect(self):
2698 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002699 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2700 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002701 """
2702 ctx = Context(TLSv1_METHOD)
2703 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002704 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002705
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002706
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002707 def test_get_cipher_name(self):
2708 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002709 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2710 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002711 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002712 server, client = self._loopback()
2713 server_cipher_name, client_cipher_name = \
2714 server.get_cipher_name(), client.get_cipher_name()
2715
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002716 self.assertIsInstance(server_cipher_name, text_type)
2717 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002718
2719 self.assertEqual(server_cipher_name, client_cipher_name)
2720
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002721
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002722 def test_get_cipher_version_before_connect(self):
2723 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002724 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2725 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002726 """
2727 ctx = Context(TLSv1_METHOD)
2728 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002729 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002730
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002731
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002732 def test_get_cipher_version(self):
2733 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002734 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2735 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002736 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002737 server, client = self._loopback()
2738 server_cipher_version, client_cipher_version = \
2739 server.get_cipher_version(), client.get_cipher_version()
2740
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002741 self.assertIsInstance(server_cipher_version, text_type)
2742 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002743
2744 self.assertEqual(server_cipher_version, client_cipher_version)
2745
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002746
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002747 def test_get_cipher_bits_before_connect(self):
2748 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002749 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2750 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002751 """
2752 ctx = Context(TLSv1_METHOD)
2753 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002754 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002755
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002756
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002757 def test_get_cipher_bits(self):
2758 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002759 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2760 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002761 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002762 server, client = self._loopback()
2763 server_cipher_bits, client_cipher_bits = \
2764 server.get_cipher_bits(), client.get_cipher_bits()
2765
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002766 self.assertIsInstance(server_cipher_bits, int)
2767 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002768
2769 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002770
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002771
Jim Shaverabff1882015-05-27 09:15:55 -04002772 def test_get_protocol_version_name(self):
2773 """
2774 :py:obj:`Connection.get_protocol_version_name()` returns a string
2775 giving the protocol version of the current connection.
2776 """
2777 server, client = self._loopback()
2778 client_protocol_version_name = client.get_protocol_version_name()
2779 server_protocol_version_name = server.get_protocol_version_name()
2780
Jim Shaver58d25732015-05-28 11:52:32 -04002781 self.assertIsInstance(server_protocol_version_name, text_type)
2782 self.assertIsInstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002783
2784 self.assertEqual(server_protocol_version_name, client_protocol_version_name)
2785
2786
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002787 def test_get_protocol_version(self):
2788 """
Alex Gaynor43307782015-09-04 09:05:45 -04002789 :py:obj:`Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002790 giving the protocol version of the current connection.
2791 """
2792 server, client = self._loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002793 client_protocol_version = client.get_protocol_version()
2794 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002795
Jim Shaverabff1882015-05-27 09:15:55 -04002796 self.assertIsInstance(server_protocol_version, int)
2797 self.assertIsInstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002798
2799 self.assertEqual(server_protocol_version, client_protocol_version)
2800
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002801
Jim Shaver208438c2015-05-28 09:52:38 -04002802
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002803class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002804 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002805 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002806 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002807 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002808 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002809 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002810 arguments.
2811 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002812 connection = Connection(Context(TLSv1_METHOD), None)
2813 self.assertRaises(TypeError, connection.get_cipher_list, None)
2814
2815
2816 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002817 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002818 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2819 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002820 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002821 connection = Connection(Context(TLSv1_METHOD), None)
2822 ciphers = connection.get_cipher_list()
2823 self.assertTrue(isinstance(ciphers, list))
2824 for cipher in ciphers:
2825 self.assertTrue(isinstance(cipher, str))
2826
2827
2828
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002829class ConnectionSendTests(TestCase, _LoopbackMixin):
2830 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002831 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002832 """
2833 def test_wrong_args(self):
2834 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002835 When called with arguments other than string argument for its first
2836 parameter or more than two arguments, :py:obj:`Connection.send` raises
2837 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002838 """
2839 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002840 self.assertRaises(TypeError, connection.send)
2841 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002842 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002843
2844
2845 def test_short_bytes(self):
2846 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002847 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002848 and returns the number of bytes sent.
2849 """
2850 server, client = self._loopback()
2851 count = server.send(b('xy'))
2852 self.assertEquals(count, 2)
2853 self.assertEquals(client.recv(2), b('xy'))
2854
Abraham Martinef063482015-03-25 14:06:24 +00002855
2856 def test_text(self):
2857 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002858 When passed a text, :py:obj:`Connection.send` transmits all of it and
2859 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002860 """
2861 server, client = self._loopback()
2862 with catch_warnings(record=True) as w:
2863 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002864 count = server.send(b"xy".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002865 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002866 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002867 WARNING_TYPE_EXPECTED
2868 ),
2869 str(w[-1].message)
2870 )
2871 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinef063482015-03-25 14:06:24 +00002872 self.assertEquals(count, 2)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002873 self.assertEquals(client.recv(2), b"xy")
Abraham Martinef063482015-03-25 14:06:24 +00002874
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002875 try:
2876 memoryview
2877 except NameError:
2878 "cannot test sending memoryview without memoryview"
2879 else:
2880 def test_short_memoryview(self):
2881 """
2882 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002883 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002884 bytes sent.
2885 """
2886 server, client = self._loopback()
2887 count = server.send(memoryview(b('xy')))
2888 self.assertEquals(count, 2)
2889 self.assertEquals(client.recv(2), b('xy'))
2890
2891
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002892 try:
2893 buffer
2894 except NameError:
2895 "cannot test sending buffer without buffer"
2896 else:
2897 def test_short_buffer(self):
2898 """
2899 When passed a buffer containing a small number of bytes,
2900 :py:obj:`Connection.send` transmits all of them and returns the number of
2901 bytes sent.
2902 """
2903 server, client = self._loopback()
2904 count = server.send(buffer(b('xy')))
2905 self.assertEquals(count, 2)
2906 self.assertEquals(client.recv(2), b('xy'))
2907
2908
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002909
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002910def _make_memoryview(size):
2911 """
2912 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2913 size.
2914 """
2915 return memoryview(bytearray(size))
2916
2917
2918
Cory Benfield62d10332014-06-15 10:03:41 +01002919class ConnectionRecvIntoTests(TestCase, _LoopbackMixin):
2920 """
2921 Tests for :py:obj:`Connection.recv_into`
2922 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002923 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002924 """
2925 Assert that when the given buffer is passed to
2926 ``Connection.recv_into``, whatever bytes are available to be received
2927 that fit into that buffer are written into that buffer.
2928 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002929 output_buffer = factory(5)
2930
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002931 server, client = self._loopback()
2932 server.send(b('xy'))
2933
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002934 self.assertEqual(client.recv_into(output_buffer), 2)
2935 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002936
2937
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002938 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002939 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002940 :py:obj:`Connection.recv_into` can be passed a ``bytearray`` instance
2941 and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002942 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002943 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002944
2945
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002946 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002947 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002948 Assert that when the given buffer is passed to ``Connection.recv_into``
2949 along with a value for ``nbytes`` that is less than the size of that
2950 buffer, only ``nbytes`` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002951 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002952 output_buffer = factory(10)
2953
Cory Benfield62d10332014-06-15 10:03:41 +01002954 server, client = self._loopback()
2955 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002956
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002957 self.assertEqual(client.recv_into(output_buffer, 5), 5)
2958 self.assertEqual(
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002959 output_buffer, bytearray(b('abcde\x00\x00\x00\x00\x00'))
2960 )
2961
2962
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002963 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002964 """
2965 When called with a ``bytearray`` instance,
2966 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter and
2967 doesn't copy in more than that number of bytes.
2968 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002969 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002970
2971
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002972 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002973 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002974 Assert that if there are more bytes available to be read from the
2975 receive buffer than would fit into the buffer passed to
2976 :py:obj:`Connection.recv_into`, only as many as fit are written into
2977 it.
Cory Benfield62d10332014-06-15 10:03:41 +01002978 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002979 output_buffer = factory(5)
2980
Cory Benfield62d10332014-06-15 10:03:41 +01002981 server, client = self._loopback()
2982 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002983
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002984 self.assertEqual(client.recv_into(output_buffer), 5)
2985 self.assertEqual(output_buffer, bytearray(b('abcde')))
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002986 rest = client.recv(5)
2987 self.assertEqual(b('fghij'), rest)
2988
2989
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002990 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002991 """
2992 When called with a ``bytearray`` instance,
2993 :py:obj:`Connection.recv_into` respects the size of the array and
2994 doesn't write more bytes into it than will fit.
2995 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002996 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002997
2998
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002999 def _really_doesnt_overfill_test(self, factory):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003000 """
3001 Assert that if the value given by ``nbytes`` is greater than the actual
3002 size of the output buffer passed to :py:obj:`Connection.recv_into`, the
3003 behavior is as if no value was given for ``nbytes`` at all.
3004 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003005 output_buffer = factory(5)
3006
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003007 server, client = self._loopback()
3008 server.send(b('abcdefghij'))
3009
3010 self.assertEqual(client.recv_into(output_buffer, 50), 5)
3011 self.assertEqual(output_buffer, bytearray(b('abcde')))
3012 rest = client.recv(5)
3013 self.assertEqual(b('fghij'), rest)
3014
3015
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003016 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003017 """
3018 When called with a ``bytearray`` instance and an ``nbytes`` value that
3019 is too large, :py:obj:`Connection.recv_into` respects the size of the
3020 array and not the ``nbytes`` value and doesn't write more bytes into
3021 the buffer than will fit.
3022 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003023 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003024
3025
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003026 def test_peek(self):
3027
3028 server, client = self._loopback()
3029 server.send(b('xy'))
3030
3031 for _ in range(2):
3032 output_buffer = bytearray(5)
3033 self.assertEqual(client.recv_into(output_buffer, flags=MSG_PEEK), 2)
3034 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
3035
3036
Cory Benfield62d10332014-06-15 10:03:41 +01003037 try:
3038 memoryview
3039 except NameError:
3040 "cannot test recv_into memoryview without memoryview"
3041 else:
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04003042 def test_memoryview_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01003043 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04003044 :py:obj:`Connection.recv_into` can be passed a ``memoryview``
3045 instance and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01003046 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003047 self._no_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003048
3049
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003050 def test_memoryview_respects_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01003051 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003052 When called with a ``memoryview`` instance,
3053 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter
3054 and doesn't copy more than that number of bytes in.
Cory Benfield62d10332014-06-15 10:03:41 +01003055 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003056 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003057
3058
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003059 def test_memoryview_doesnt_overfill(self):
Cory Benfield62d10332014-06-15 10:03:41 +01003060 """
Jean-Paul Calderone8fd82552015-03-15 17:21:07 -04003061 When called with a ``memoryview`` instance,
3062 :py:obj:`Connection.recv_into` respects the size of the array and
3063 doesn't write more bytes into it than will fit.
Cory Benfield62d10332014-06-15 10:03:41 +01003064 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003065 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003066
3067
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003068 def test_memoryview_really_doesnt_overfill(self):
3069 """
3070 When called with a ``memoryview`` instance and an ``nbytes`` value
3071 that is too large, :py:obj:`Connection.recv_into` respects the size
3072 of the array and not the ``nbytes`` value and doesn't write more
3073 bytes into the buffer than will fit.
3074 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003075 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003076
3077
Cory Benfield62d10332014-06-15 10:03:41 +01003078
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003079class ConnectionSendallTests(TestCase, _LoopbackMixin):
3080 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003081 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003082 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003083 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003084 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003085 When called with arguments other than a string argument for its first
3086 parameter or with more than two arguments, :py:obj:`Connection.sendall`
3087 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003088 """
3089 connection = Connection(Context(TLSv1_METHOD), None)
3090 self.assertRaises(TypeError, connection.sendall)
3091 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003092 self.assertRaises(
3093 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003094
3095
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003096 def test_short(self):
3097 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003098 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003099 it.
3100 """
3101 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04003102 server.sendall(b('x'))
3103 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003104
3105
Abraham Martinef063482015-03-25 14:06:24 +00003106 def test_text(self):
3107 """
Jean-Paul Calderone93477422015-04-13 20:38:57 -04003108 :py:obj:`Connection.sendall` transmits all the content in the string
3109 passed to it raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003110 """
3111 server, client = self._loopback()
3112 with catch_warnings(record=True) as w:
3113 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003114 server.sendall(b"x".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003115 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003116 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003117 WARNING_TYPE_EXPECTED
3118 ),
3119 str(w[-1].message)
3120 )
3121 self.assertIs(w[-1].category, DeprecationWarning)
3122 self.assertEquals(client.recv(1), b"x")
Abraham Martinef063482015-03-25 14:06:24 +00003123
3124
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003125 try:
3126 memoryview
3127 except NameError:
3128 "cannot test sending memoryview without memoryview"
3129 else:
3130 def test_short_memoryview(self):
3131 """
3132 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003133 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003134 """
3135 server, client = self._loopback()
3136 server.sendall(memoryview(b('x')))
3137 self.assertEquals(client.recv(1), b('x'))
3138
3139
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003140 try:
3141 buffer
3142 except NameError:
3143 "cannot test sending buffers without buffers"
3144 else:
3145 def test_short_buffers(self):
3146 """
3147 When passed a buffer containing a small number of bytes,
3148 :py:obj:`Connection.sendall` transmits all of them.
3149 """
3150 server, client = self._loopback()
3151 server.sendall(buffer(b('x')))
3152 self.assertEquals(client.recv(1), b('x'))
3153
3154
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003155 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003156 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003157 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003158 it even if this requires multiple calls of an underlying write function.
3159 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003160 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003161 # Should be enough, underlying SSL_write should only do 16k at a time.
3162 # On Windows, after 32k of bytes the write will block (forever - because
3163 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04003164 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003165 server.sendall(message)
3166 accum = []
3167 received = 0
3168 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003169 data = client.recv(1024)
3170 accum.append(data)
3171 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04003172 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003173
3174
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003175 def test_closed(self):
3176 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003177 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003178 write error from the low level write call.
3179 """
3180 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003181 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003182 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003183 if platform == "win32":
3184 self.assertEqual(exc.args[0], ESHUTDOWN)
3185 else:
3186 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003187
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003188
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04003189
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003190class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
3191 """
3192 Tests for SSL renegotiation APIs.
3193 """
3194 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003195 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003196 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003197 arguments.
3198 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003199 connection = Connection(Context(TLSv1_METHOD), None)
3200 self.assertRaises(TypeError, connection.renegotiate, None)
3201
3202
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003203 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003204 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003205 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003206 any arguments.
3207 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003208 connection = Connection(Context(TLSv1_METHOD), None)
3209 self.assertRaises(TypeError, connection.total_renegotiations, None)
3210
3211
3212 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003213 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003214 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003215 renegotiations have happened.
3216 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003217 connection = Connection(Context(TLSv1_METHOD), None)
3218 self.assertEquals(connection.total_renegotiations(), 0)
3219
3220
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003221# def test_renegotiate(self):
3222# """
3223# """
3224# server, client = self._loopback()
3225
3226# server.send("hello world")
3227# self.assertEquals(client.recv(len("hello world")), "hello world")
3228
3229# self.assertEquals(server.total_renegotiations(), 0)
3230# self.assertTrue(server.renegotiate())
3231
3232# server.setblocking(False)
3233# client.setblocking(False)
3234# while server.renegotiate_pending():
3235# client.do_handshake()
3236# server.do_handshake()
3237
3238# self.assertEquals(server.total_renegotiations(), 1)
3239
3240
3241
3242
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003243class ErrorTests(TestCase):
3244 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003245 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003246 """
3247 def test_type(self):
3248 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003249 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003250 """
3251 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05003252 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05003253
3254
3255
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003256class ConstantsTests(TestCase):
3257 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003258 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003259
3260 These are values defined by OpenSSL intended only to be used as flags to
3261 OpenSSL APIs. The only assertions it seems can be made about them is
3262 their values.
3263 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003264 # unittest.TestCase has no skip mechanism
3265 if OP_NO_QUERY_MTU is not None:
3266 def test_op_no_query_mtu(self):
3267 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003268 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003269 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003270 """
3271 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
3272 else:
3273 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003274
3275
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003276 if OP_COOKIE_EXCHANGE is not None:
3277 def test_op_cookie_exchange(self):
3278 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003279 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003280 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003281 """
3282 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
3283 else:
3284 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003285
3286
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003287 if OP_NO_TICKET is not None:
3288 def test_op_no_ticket(self):
3289 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003290 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003291 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003292 """
3293 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04003294 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05003295 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05003296
3297
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003298 if OP_NO_COMPRESSION is not None:
3299 def test_op_no_compression(self):
3300 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04003301 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
3302 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003303 """
3304 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
3305 else:
3306 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3307
3308
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003309 def test_sess_cache_off(self):
3310 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003311 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3312 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003313 """
3314 self.assertEqual(0x0, SESS_CACHE_OFF)
3315
3316
3317 def test_sess_cache_client(self):
3318 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003319 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3320 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003321 """
3322 self.assertEqual(0x1, SESS_CACHE_CLIENT)
3323
3324
3325 def test_sess_cache_server(self):
3326 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003327 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3328 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003329 """
3330 self.assertEqual(0x2, SESS_CACHE_SERVER)
3331
3332
3333 def test_sess_cache_both(self):
3334 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003335 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3336 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003337 """
3338 self.assertEqual(0x3, SESS_CACHE_BOTH)
3339
3340
3341 def test_sess_cache_no_auto_clear(self):
3342 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003343 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3344 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3345 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003346 """
3347 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
3348
3349
3350 def test_sess_cache_no_internal_lookup(self):
3351 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003352 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3353 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3354 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003355 """
3356 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
3357
3358
3359 def test_sess_cache_no_internal_store(self):
3360 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003361 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3362 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3363 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003364 """
3365 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
3366
3367
3368 def test_sess_cache_no_internal(self):
3369 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003370 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3371 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
3372 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003373 """
3374 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
3375
3376
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04003377
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003378class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05003379 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003380 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003381 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003382 def _server(self, sock):
3383 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003384 Create a new server-side SSL :py:obj:`Connection` object wrapped around
3385 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003386 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003387 # Create the server side Connection. This is mostly setup boilerplate
3388 # - use TLSv1, use a particular certificate, etc.
3389 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003390 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
3391 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 -04003392 server_store = server_ctx.get_cert_store()
3393 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3394 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3395 server_ctx.check_privatekey()
3396 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003397 # Here the Connection is actually created. If None is passed as the 2nd
3398 # parameter, it indicates a memory BIO should be created.
3399 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003400 server_conn.set_accept_state()
3401 return server_conn
3402
3403
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003404 def _client(self, sock):
3405 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003406 Create a new client-side SSL :py:obj:`Connection` object wrapped around
3407 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003408 """
3409 # Now create the client side Connection. Similar boilerplate to the
3410 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003411 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003412 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
3413 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 -04003414 client_store = client_ctx.get_cert_store()
3415 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
3416 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
3417 client_ctx.check_privatekey()
3418 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003419 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003420 client_conn.set_connect_state()
3421 return client_conn
3422
3423
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003424 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003425 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003426 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003427 reading from the output of each and writing those bytes to the input of
3428 the other and in this way establish a connection and exchange
3429 application-level bytes with each other.
3430 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003431 server_conn = self._server(None)
3432 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003433
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003434 # There should be no key or nonces yet.
3435 self.assertIdentical(server_conn.master_key(), None)
3436 self.assertIdentical(server_conn.client_random(), None)
3437 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003438
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003439 # First, the handshake needs to happen. We'll deliver bytes back and
3440 # forth between the client and server until neither of them feels like
3441 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003442 self.assertIdentical(
3443 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003444
3445 # Now that the handshake is done, there should be a key and nonces.
3446 self.assertNotIdentical(server_conn.master_key(), None)
3447 self.assertNotIdentical(server_conn.client_random(), None)
3448 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04003449 self.assertEquals(server_conn.client_random(), client_conn.client_random())
3450 self.assertEquals(server_conn.server_random(), client_conn.server_random())
3451 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
3452 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003453
3454 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003455 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05003456
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003457 server_conn.write(important_message)
3458 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003459 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003460 (client_conn, important_message))
3461
3462 client_conn.write(important_message[::-1])
3463 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003464 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003465 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003466
3467
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003468 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003469 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003470 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003471
3472 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09003473 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003474 this test fails, there must be a problem outside the memory BIO
3475 code, as no memory BIO is involved here). Even though this isn't a
3476 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003477 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04003478 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003479
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003480 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05003481 client_conn.send(important_message)
3482 msg = server_conn.recv(1024)
3483 self.assertEqual(msg, important_message)
3484
3485 # Again in the other direction, just for fun.
3486 important_message = important_message[::-1]
3487 server_conn.send(important_message)
3488 msg = client_conn.recv(1024)
3489 self.assertEqual(msg, important_message)
3490
3491
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04003492 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003493 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003494 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
3495 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003496 """
3497 context = Context(SSLv3_METHOD)
3498 client = socket()
3499 clientSSL = Connection(context, client)
Alex Gaynor43307782015-09-04 09:05:45 -04003500 self.assertRaises(TypeError, clientSSL.bio_read, 100)
3501 self.assertRaises(TypeError, clientSSL.bio_write, "foo")
Alex Gaynor7e8b61e2015-09-04 13:13:05 -04003502 self.assertRaises(TypeError, clientSSL.bio_shutdown)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003503
3504
3505 def test_outgoingOverflow(self):
3506 """
3507 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09003508 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003509 returned and that many bytes from the beginning of the input can be
3510 read from the other end of the connection.
3511 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003512 server = self._server(None)
3513 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003514
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003515 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003516
3517 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003518 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003519 # Sanity check. We're trying to test what happens when the entire
3520 # input can't be sent. If the entire input was sent, this test is
3521 # meaningless.
3522 self.assertTrue(sent < size)
3523
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003524 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003525 self.assertIdentical(receiver, server)
3526
3527 # We can rely on all of these bytes being received at once because
3528 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
3529 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003530
3531
3532 def test_shutdown(self):
3533 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003534 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
3535 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003536 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003537 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003538 server.bio_shutdown()
3539 e = self.assertRaises(Error, server.recv, 1024)
3540 # We don't want WantReadError or ZeroReturnError or anything - it's a
3541 # handshake failure.
3542 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003543
3544
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003545 def test_unexpectedEndOfFile(self):
3546 """
3547 If the connection is lost before an orderly SSL shutdown occurs,
3548 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
3549 "Unexpected EOF".
3550 """
3551 server_conn, client_conn = self._loopback()
3552 client_conn.sock_shutdown(SHUT_RDWR)
3553 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
3554 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
3555
3556
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003557 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003558 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003559 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 -04003560
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003561 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003562 before the client and server are connected to each other. This
3563 function should specify a list of CAs for the server to send to the
3564 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09003565 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003566 times.
3567 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003568 server = self._server(None)
3569 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003570 self.assertEqual(client.get_client_ca_list(), [])
3571 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003572 ctx = server.get_context()
3573 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003574 self.assertEqual(client.get_client_ca_list(), [])
3575 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003576 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003577 self.assertEqual(client.get_client_ca_list(), expected)
3578 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003579
3580
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003581 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003582 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003583 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003584 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003585 """
3586 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003587 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
3588 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
3589 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003590
3591
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003592 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003593 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003594 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003595 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09003596 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003597 after the connection is set up.
3598 """
3599 def no_ca(ctx):
3600 ctx.set_client_ca_list([])
3601 return []
3602 self._check_client_ca_list(no_ca)
3603
3604
3605 def test_set_one_ca_list(self):
3606 """
3607 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003608 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003609 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003610 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003611 X509Name after the connection is set up.
3612 """
3613 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3614 cadesc = cacert.get_subject()
3615 def single_ca(ctx):
3616 ctx.set_client_ca_list([cadesc])
3617 return [cadesc]
3618 self._check_client_ca_list(single_ca)
3619
3620
3621 def test_set_multiple_ca_list(self):
3622 """
3623 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003624 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003625 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003626 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003627 X509Names after the connection is set up.
3628 """
3629 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3630 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3631
3632 sedesc = secert.get_subject()
3633 cldesc = clcert.get_subject()
3634
3635 def multiple_ca(ctx):
3636 L = [sedesc, cldesc]
3637 ctx.set_client_ca_list(L)
3638 return L
3639 self._check_client_ca_list(multiple_ca)
3640
3641
3642 def test_reset_ca_list(self):
3643 """
3644 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09003645 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003646 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003647 """
3648 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3649 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3650 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3651
3652 cadesc = cacert.get_subject()
3653 sedesc = secert.get_subject()
3654 cldesc = clcert.get_subject()
3655
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003656 def changed_ca(ctx):
3657 ctx.set_client_ca_list([sedesc, cldesc])
3658 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003659 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003660 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003661
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003662
3663 def test_mutated_ca_list(self):
3664 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003665 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003666 afterwards, this does not affect the list of CA names sent to the
3667 client.
3668 """
3669 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3670 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3671
3672 cadesc = cacert.get_subject()
3673 sedesc = secert.get_subject()
3674
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003675 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003676 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003677 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003678 L.append(sedesc)
3679 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003680 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003681
3682
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003683 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003684 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003685 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003686 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003687 """
3688 ctx = Context(TLSv1_METHOD)
3689 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003690 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003691 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003692 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003693
3694
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003695 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003696 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003697 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09003698 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003699 """
3700 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3701 cadesc = cacert.get_subject()
3702 def single_ca(ctx):
3703 ctx.add_client_ca(cacert)
3704 return [cadesc]
3705 self._check_client_ca_list(single_ca)
3706
3707
3708 def test_multiple_add_client_ca(self):
3709 """
3710 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09003711 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003712 """
3713 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3714 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3715
3716 cadesc = cacert.get_subject()
3717 sedesc = secert.get_subject()
3718
3719 def multiple_ca(ctx):
3720 ctx.add_client_ca(cacert)
3721 ctx.add_client_ca(secert)
3722 return [cadesc, sedesc]
3723 self._check_client_ca_list(multiple_ca)
3724
3725
3726 def test_set_and_add_client_ca(self):
3727 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003728 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
3729 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003730 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003731 """
3732 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3733 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3734 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3735
3736 cadesc = cacert.get_subject()
3737 sedesc = secert.get_subject()
3738 cldesc = clcert.get_subject()
3739
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003740 def mixed_set_add_ca(ctx):
3741 ctx.set_client_ca_list([cadesc, sedesc])
3742 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003743 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003744 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003745
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003746
3747 def test_set_after_add_client_ca(self):
3748 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003749 A call to :py:obj:`Context.set_client_ca_list` after a call to
3750 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003751 call with the names specified by the latter cal.
3752 """
3753 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3754 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3755 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3756
3757 cadesc = cacert.get_subject()
3758 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003759
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003760 def set_replaces_add_ca(ctx):
3761 ctx.add_client_ca(clcert)
3762 ctx.set_client_ca_list([cadesc])
3763 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003764 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003765 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003766
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003767
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003768
3769class ConnectionBIOTests(TestCase):
3770 """
3771 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3772 """
3773 def test_wantReadError(self):
3774 """
3775 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
3776 if there are no bytes available to be read from the BIO.
3777 """
3778 ctx = Context(TLSv1_METHOD)
3779 conn = Connection(ctx, None)
3780 self.assertRaises(WantReadError, conn.bio_read, 1024)
3781
3782
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003783 def test_buffer_size(self):
3784 """
3785 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3786 number of bytes to read and return.
3787 """
3788 ctx = Context(TLSv1_METHOD)
3789 conn = Connection(ctx, None)
3790 conn.set_connect_state()
3791 try:
3792 conn.do_handshake()
3793 except WantReadError:
3794 pass
3795 data = conn.bio_read(2)
3796 self.assertEqual(2, len(data))
3797
3798
3799 if not PY3:
3800 def test_buffer_size_long(self):
3801 """
3802 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3803 :py:obj:`long` as well as :py:obj:`int`.
3804 """
3805 ctx = Context(TLSv1_METHOD)
3806 conn = Connection(ctx, None)
3807 conn.set_connect_state()
3808 try:
3809 conn.do_handshake()
3810 except WantReadError:
3811 pass
3812 data = conn.bio_read(long(2))
3813 self.assertEqual(2, len(data))
3814
3815
3816
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003817
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003818class InfoConstantTests(TestCase):
3819 """
3820 Tests for assorted constants exposed for use in info callbacks.
3821 """
3822 def test_integers(self):
3823 """
3824 All of the info constants are integers.
3825
3826 This is a very weak test. It would be nice to have one that actually
3827 verifies that as certain info events happen, the value passed to the
3828 info callback matches up with the constant exposed by OpenSSL.SSL.
3829 """
3830 for const in [
3831 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3832 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3833 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3834 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3835 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
3836 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
3837
3838 self.assertTrue(isinstance(const, int))
3839
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003840
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003841if __name__ == '__main__':
3842 main()