blob: caa9d02152a963e655583bd2bc7897173cdad834 [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 Calderone210c0f32015-04-12 09:20:31 -040010from sys import platform, version_info, getfilesystemencoding
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070011from socket import SHUT_RDWR, error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040012from os import makedirs
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040013from os.path import join
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -040014from unittest import main
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040015from weakref import ref
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050016
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -040017from six import PY3, text_type, u
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050018
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040019from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080020from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040021from OpenSSL.crypto import dump_privatekey, load_privatekey
22from OpenSSL.crypto import dump_certificate, load_certificate
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040023from OpenSSL.crypto import get_elliptic_curves
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040024
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040025from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
26from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040027from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040028from OpenSSL.SSL import (
29 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
30 TLSv1_1_METHOD, TLSv1_2_METHOD)
31from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040032from OpenSSL.SSL import (
33 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040034
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040035from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050036 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
37 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
38 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
39
40from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070041 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050042from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070043 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040044
Cory Benfieldba1820d2015-04-13 17:39:12 -040045from OpenSSL._util import lib as _lib
46
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -040047from OpenSSL.test.util import NON_ASCII, TestCase, b
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040048from OpenSSL.test.test_crypto import (
49 cleartextCertificatePEM, cleartextPrivateKeyPEM)
50from OpenSSL.test.test_crypto import (
51 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
52 root_cert_pem)
53
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050054try:
55 from OpenSSL.SSL import OP_NO_QUERY_MTU
56except ImportError:
57 OP_NO_QUERY_MTU = None
58try:
59 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
60except ImportError:
61 OP_COOKIE_EXCHANGE = None
62try:
63 from OpenSSL.SSL import OP_NO_TICKET
64except ImportError:
65 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040066
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040067try:
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -040068 from OpenSSL.SSL import OP_NO_COMPRESSION
69except ImportError:
70 OP_NO_COMPRESSION = None
71
72try:
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040073 from OpenSSL.SSL import MODE_RELEASE_BUFFERS
74except ImportError:
75 MODE_RELEASE_BUFFERS = None
76
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040077try:
78 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
79except ImportError:
80 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
81
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040082from OpenSSL.SSL import (
83 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
84 SSL_ST_OK, SSL_ST_RENEGOTIATE,
85 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
86 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
87 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
88 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040089
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040090# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
91# to use)
92dhparam = """\
93-----BEGIN DH PARAMETERS-----
94MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
95-----END DH PARAMETERS-----
96"""
97
98
Jean-Paul Calderone05826732015-04-12 11:38:49 -040099def join_bytes_or_unicode(prefix, suffix):
100 """
101 Join two path components of either ``bytes`` or ``unicode``.
102
103 The return type is the same as the type of ``prefix``.
104 """
105 # If the types are the same, nothing special is necessary.
106 if type(prefix) == type(suffix):
107 return join(prefix, suffix)
108
109 # Otherwise, coerce suffix to the type of prefix.
110 if isinstance(prefix, text_type):
111 return join(prefix, suffix.decode(getfilesystemencoding()))
112 else:
113 return join(prefix, suffix.encode(getfilesystemencoding()))
114
115
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400116def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400117 return ok
118
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400119
Rick Deanb1ccd562009-07-09 23:52:39 -0500120def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400121 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400122 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400123 """
124 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500125 port = socket()
126 port.bind(('', 0))
127 port.listen(1)
128 client = socket()
129 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400130 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400131 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500132 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500133
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400134 # Let's pass some unencrypted data to make sure our socket connection is
135 # fine. Just one byte, so we don't have to worry about buffers getting
136 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400137 server.send(b("x"))
138 assert client.recv(1024) == b("x")
139 client.send(b("y"))
140 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500141
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400142 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400143 server.setblocking(False)
144 client.setblocking(False)
145
Rick Deanb1ccd562009-07-09 23:52:39 -0500146 return (server, client)
147
148
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400149
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400150def handshake(client, server):
151 conns = [client, server]
152 while conns:
153 for conn in conns:
154 try:
155 conn.do_handshake()
156 except WantReadError:
157 pass
158 else:
159 conns.remove(conn)
160
161
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400162def _create_certificate_chain():
163 """
164 Construct and return a chain of certificates.
165
166 1. A new self-signed certificate authority certificate (cacert)
167 2. A new intermediate certificate signed by cacert (icert)
168 3. A new server certificate signed by icert (scert)
169 """
170 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
171
172 # Step 1
173 cakey = PKey()
174 cakey.generate_key(TYPE_RSA, 512)
175 cacert = X509()
176 cacert.get_subject().commonName = "Authority Certificate"
177 cacert.set_issuer(cacert.get_subject())
178 cacert.set_pubkey(cakey)
179 cacert.set_notBefore(b("20000101000000Z"))
180 cacert.set_notAfter(b("20200101000000Z"))
181 cacert.add_extensions([caext])
182 cacert.set_serial_number(0)
183 cacert.sign(cakey, "sha1")
184
185 # Step 2
186 ikey = PKey()
187 ikey.generate_key(TYPE_RSA, 512)
188 icert = X509()
189 icert.get_subject().commonName = "Intermediate Certificate"
190 icert.set_issuer(cacert.get_subject())
191 icert.set_pubkey(ikey)
192 icert.set_notBefore(b("20000101000000Z"))
193 icert.set_notAfter(b("20200101000000Z"))
194 icert.add_extensions([caext])
195 icert.set_serial_number(0)
196 icert.sign(cakey, "sha1")
197
198 # Step 3
199 skey = PKey()
200 skey.generate_key(TYPE_RSA, 512)
201 scert = X509()
202 scert.get_subject().commonName = "Server Certificate"
203 scert.set_issuer(icert.get_subject())
204 scert.set_pubkey(skey)
205 scert.set_notBefore(b("20000101000000Z"))
206 scert.set_notAfter(b("20200101000000Z"))
207 scert.add_extensions([
208 X509Extension(b('basicConstraints'), True, b('CA:false'))])
209 scert.set_serial_number(0)
210 scert.sign(ikey, "sha1")
211
212 return [(cakey, cacert), (ikey, icert), (skey, scert)]
213
214
215
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400216class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400217 """
218 Helper mixin which defines methods for creating a connected socket pair and
219 for forcing two connected SSL sockets to talk to each other via memory BIOs.
220 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500221 def _loopbackClientFactory(self, socket):
222 client = Connection(Context(TLSv1_METHOD), socket)
223 client.set_connect_state()
224 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400225
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500226
227 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400228 ctx = Context(TLSv1_METHOD)
229 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
230 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500231 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400232 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500233 return server
234
235
236 def _loopback(self, serverFactory=None, clientFactory=None):
237 if serverFactory is None:
238 serverFactory = self._loopbackServerFactory
239 if clientFactory is None:
240 clientFactory = self._loopbackClientFactory
241
242 (server, client) = socket_pair()
243 server = serverFactory(server)
244 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400245
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400246 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400247
248 server.setblocking(True)
249 client.setblocking(True)
250 return server, client
251
252
253 def _interactInMemory(self, client_conn, server_conn):
254 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900255 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400256 objects. Copy bytes back and forth between their send/receive buffers
257 for as long as there is anything to copy. When there is nothing more
Jonathan Ballet648875f2011-07-16 14:14:58 +0900258 to copy, return :py:obj:`None`. If one of them actually manages to deliver
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400259 some application bytes, return a two-tuple of the connection from which
260 the bytes were read and the bytes themselves.
261 """
262 wrote = True
263 while wrote:
264 # Loop until neither side has anything to say
265 wrote = False
266
267 # Copy stuff from each side's send buffer to the other side's
268 # receive buffer.
269 for (read, write) in [(client_conn, server_conn),
270 (server_conn, client_conn)]:
271
272 # Give the side a chance to generate some more bytes, or
273 # succeed.
274 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400275 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400276 except WantReadError:
277 # It didn't succeed, so we'll hope it generated some
278 # output.
279 pass
280 else:
281 # It did succeed, so we'll stop now and let the caller deal
282 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400283 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400284
285 while True:
286 # Keep copying as long as there's more stuff there.
287 try:
288 dirty = read.bio_read(4096)
289 except WantReadError:
290 # Okay, nothing more waiting to be sent. Stop
291 # processing this send buffer.
292 break
293 else:
294 # Keep track of the fact that someone generated some
295 # output.
296 wrote = True
297 write.bio_write(dirty)
298
299
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400300 def _handshakeInMemory(self, client_conn, server_conn):
Jean-Paul Calderoneb2b40782014-05-06 08:47:40 -0400301 """
302 Perform the TLS handshake between two :py:class:`Connection` instances
303 connected to each other via memory BIOs.
304 """
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400305 client_conn.set_connect_state()
306 server_conn.set_accept_state()
307
308 for conn in [client_conn, server_conn]:
309 try:
310 conn.do_handshake()
311 except WantReadError:
312 pass
313
314 self._interactInMemory(client_conn, server_conn)
315
316
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400317
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400318class VersionTests(TestCase):
319 """
320 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900321 :py:obj:`OpenSSL.SSL.SSLeay_version` and
322 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400323 """
324 def test_OPENSSL_VERSION_NUMBER(self):
325 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900326 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400327 byte and the patch, fix, minor, and major versions in the
328 nibbles above that.
329 """
330 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
331
332
333 def test_SSLeay_version(self):
334 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900335 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400336 one of a number of version strings based on that indicator.
337 """
338 versions = {}
339 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
340 SSLEAY_PLATFORM, SSLEAY_DIR]:
341 version = SSLeay_version(t)
342 versions[version] = t
343 self.assertTrue(isinstance(version, bytes))
344 self.assertEqual(len(versions), 5)
345
346
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400347
348class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400349 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900350 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400351 """
352 def test_method(self):
353 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900354 :py:obj:`Context` can be instantiated with one of :py:obj:`SSLv2_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400355 :py:obj:`SSLv3_METHOD`, :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
356 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400357 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400358 methods = [
359 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
360 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400361 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400362
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400363
364 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
365 for meth in maybe:
366 try:
367 Context(meth)
368 except (Error, ValueError):
369 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
370 # don't. Difficult to say in advance.
371 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400372
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400373 self.assertRaises(TypeError, Context, "")
374 self.assertRaises(ValueError, Context, 10)
375
376
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500377 if not PY3:
378 def test_method_long(self):
379 """
380 On Python 2 :py:class:`Context` accepts values of type
381 :py:obj:`long` as well as :py:obj:`int`.
382 """
383 Context(long(TLSv1_METHOD))
384
385
386
Rick Deane15b1472009-07-09 15:53:42 -0500387 def test_type(self):
388 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900389 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400390 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500391 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400392 self.assertIdentical(Context, ContextType)
393 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500394
395
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400396 def test_use_privatekey(self):
397 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900398 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400399 """
400 key = PKey()
401 key.generate_key(TYPE_RSA, 128)
402 ctx = Context(TLSv1_METHOD)
403 ctx.use_privatekey(key)
404 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400405
406
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800407 def test_use_privatekey_file_missing(self):
408 """
409 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error`
410 when passed the name of a file which does not exist.
411 """
412 ctx = Context(TLSv1_METHOD)
413 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
414
415
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400416 def _use_privatekey_file_test(self, pemfile, filetype):
417 """
418 Verify that calling ``Context.use_privatekey_file`` with the given
419 arguments does not raise an exception.
420 """
421 key = PKey()
422 key.generate_key(TYPE_RSA, 128)
423
424 with open(pemfile, "wt") as pem:
425 pem.write(
426 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
427 )
428
429 ctx = Context(TLSv1_METHOD)
430 ctx.use_privatekey_file(pemfile, filetype)
431
432
433 def test_use_privatekey_file_bytes(self):
434 """
435 A private key can be specified from a file by passing a ``bytes``
436 instance giving the file name to ``Context.use_privatekey_file``.
437 """
438 self._use_privatekey_file_test(
439 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
440 FILETYPE_PEM,
441 )
442
443
444 def test_use_privatekey_file_unicode(self):
445 """
446 A private key can be specified from a file by passing a ``unicode``
447 instance giving the file name to ``Context.use_privatekey_file``.
448 """
449 self._use_privatekey_file_test(
450 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
451 FILETYPE_PEM,
452 )
453
454
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500455 if not PY3:
456 def test_use_privatekey_file_long(self):
457 """
458 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
459 filetype of type :py:obj:`long` as well as :py:obj:`int`.
460 """
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400461 self._use_privatekey_file_test(self.mktemp(), long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500462
463
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800464 def test_use_certificate_wrong_args(self):
465 """
466 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
467 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as an
468 argument.
469 """
470 ctx = Context(TLSv1_METHOD)
471 self.assertRaises(TypeError, ctx.use_certificate)
472 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
473 self.assertRaises(TypeError, ctx.use_certificate, X509(), "hello, world")
474
475
476 def test_use_certificate_uninitialized(self):
477 """
478 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
479 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
480 initialized (ie, which does not actually have any certificate data).
481 """
482 ctx = Context(TLSv1_METHOD)
483 self.assertRaises(Error, ctx.use_certificate, X509())
484
485
486 def test_use_certificate(self):
487 """
488 :py:obj:`Context.use_certificate` sets the certificate which will be
489 used to identify connections created using the context.
490 """
491 # TODO
492 # Hard to assert anything. But we could set a privatekey then ask
493 # OpenSSL if the cert and key agree using check_privatekey. Then as
494 # long as check_privatekey works right we're good...
495 ctx = Context(TLSv1_METHOD)
496 ctx.use_certificate(load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
497
498
499 def test_use_certificate_file_wrong_args(self):
500 """
501 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
502 called with zero arguments or more than two arguments, or if the first
503 argument is not a byte string or the second argumnent is not an integer.
504 """
505 ctx = Context(TLSv1_METHOD)
506 self.assertRaises(TypeError, ctx.use_certificate_file)
507 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile", object())
508 self.assertRaises(
509 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM, object())
510 self.assertRaises(
511 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
512 self.assertRaises(
513 TypeError, ctx.use_certificate_file, b"somefile", object())
514
515
516 def test_use_certificate_file_missing(self):
517 """
518 :py:obj:`Context.use_certificate_file` raises
519 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does not
520 exist.
521 """
522 ctx = Context(TLSv1_METHOD)
523 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
524
525
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400526 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800527 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400528 Verify that calling ``Context.use_certificate_file`` with the given
529 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800530 """
531 # TODO
532 # Hard to assert anything. But we could set a privatekey then ask
533 # OpenSSL if the cert and key agree using check_privatekey. Then as
534 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400535 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800536 pem_file.write(cleartextCertificatePEM)
537
538 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400539 ctx.use_certificate_file(certificate_file)
540
541
542 def test_use_certificate_file_bytes(self):
543 """
544 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
545 ``bytes`` filename) which will be used to identify connections created
546 using the context.
547 """
548 filename = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
549 self._use_certificate_file_test(filename)
550
551
552 def test_use_certificate_file_unicode(self):
553 """
554 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
555 ``bytes`` filename) which will be used to identify connections created
556 using the context.
557 """
558 filename = self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
559 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800560
561
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500562 if not PY3:
563 def test_use_certificate_file_long(self):
564 """
565 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
566 filetype of type :py:obj:`long` as well as :py:obj:`int`.
567 """
568 pem_filename = self.mktemp()
569 with open(pem_filename, "wb") as pem_file:
570 pem_file.write(cleartextCertificatePEM)
571
572 ctx = Context(TLSv1_METHOD)
573 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
574
575
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500576 def test_check_privatekey_valid(self):
577 """
578 :py:obj:`Context.check_privatekey` returns :py:obj:`None` if the
579 :py:obj:`Context` instance has been configured to use a matched key and
580 certificate pair.
581 """
582 key = load_privatekey(FILETYPE_PEM, client_key_pem)
583 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
584 context = Context(TLSv1_METHOD)
585 context.use_privatekey(key)
586 context.use_certificate(cert)
587 self.assertIs(None, context.check_privatekey())
588
589
590 def test_check_privatekey_invalid(self):
591 """
592 :py:obj:`Context.check_privatekey` raises :py:obj:`Error` if the
593 :py:obj:`Context` instance has been configured to use a key and
594 certificate pair which don't relate to each other.
595 """
596 key = load_privatekey(FILETYPE_PEM, client_key_pem)
597 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
598 context = Context(TLSv1_METHOD)
599 context.use_privatekey(key)
600 context.use_certificate(cert)
601 self.assertRaises(Error, context.check_privatekey)
602
603
604 def test_check_privatekey_wrong_args(self):
605 """
606 :py:obj:`Context.check_privatekey` raises :py:obj:`TypeError` if called
607 with other than no arguments.
608 """
609 context = Context(TLSv1_METHOD)
610 self.assertRaises(TypeError, context.check_privatekey, object())
611
612
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400613 def test_set_app_data_wrong_args(self):
614 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900615 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called with other than
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400616 one argument.
617 """
618 context = Context(TLSv1_METHOD)
619 self.assertRaises(TypeError, context.set_app_data)
620 self.assertRaises(TypeError, context.set_app_data, None, None)
621
622
623 def test_get_app_data_wrong_args(self):
624 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900625 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400626 arguments.
627 """
628 context = Context(TLSv1_METHOD)
629 self.assertRaises(TypeError, context.get_app_data, None)
630
631
632 def test_app_data(self):
633 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900634 :py:obj:`Context.set_app_data` stores an object for later retrieval using
635 :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400636 """
637 app_data = object()
638 context = Context(TLSv1_METHOD)
639 context.set_app_data(app_data)
640 self.assertIdentical(context.get_app_data(), app_data)
641
642
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400643 def test_set_options_wrong_args(self):
644 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900645 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with the wrong
646 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400647 """
648 context = Context(TLSv1_METHOD)
649 self.assertRaises(TypeError, context.set_options)
650 self.assertRaises(TypeError, context.set_options, None)
651 self.assertRaises(TypeError, context.set_options, 1, None)
652
653
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500654 def test_set_options(self):
655 """
656 :py:obj:`Context.set_options` returns the new options value.
657 """
658 context = Context(TLSv1_METHOD)
659 options = context.set_options(OP_NO_SSLv2)
660 self.assertTrue(OP_NO_SSLv2 & options)
661
662
663 if not PY3:
664 def test_set_options_long(self):
665 """
666 On Python 2 :py:obj:`Context.set_options` accepts values of type
667 :py:obj:`long` as well as :py:obj:`int`.
668 """
669 context = Context(TLSv1_METHOD)
670 options = context.set_options(long(OP_NO_SSLv2))
671 self.assertTrue(OP_NO_SSLv2 & options)
672
673
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300674 def test_set_mode_wrong_args(self):
675 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400676 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with the wrong
677 number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300678 """
679 context = Context(TLSv1_METHOD)
680 self.assertRaises(TypeError, context.set_mode)
681 self.assertRaises(TypeError, context.set_mode, None)
682 self.assertRaises(TypeError, context.set_mode, 1, None)
683
684
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400685 if MODE_RELEASE_BUFFERS is not None:
686 def test_set_mode(self):
687 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400688 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the newly
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400689 set mode.
690 """
691 context = Context(TLSv1_METHOD)
692 self.assertTrue(
693 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500694
695 if not PY3:
696 def test_set_mode_long(self):
697 """
698 On Python 2 :py:obj:`Context.set_mode` accepts values of type
699 :py:obj:`long` as well as :py:obj:`int`.
700 """
701 context = Context(TLSv1_METHOD)
702 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
703 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400704 else:
705 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
706
707
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400708 def test_set_timeout_wrong_args(self):
709 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900710 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with the wrong
711 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400712 """
713 context = Context(TLSv1_METHOD)
714 self.assertRaises(TypeError, context.set_timeout)
715 self.assertRaises(TypeError, context.set_timeout, None)
716 self.assertRaises(TypeError, context.set_timeout, 1, None)
717
718
719 def test_get_timeout_wrong_args(self):
720 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900721 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400722 """
723 context = Context(TLSv1_METHOD)
724 self.assertRaises(TypeError, context.get_timeout, None)
725
726
727 def test_timeout(self):
728 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900729 :py:obj:`Context.set_timeout` sets the session timeout for all connections
730 created using the context object. :py:obj:`Context.get_timeout` retrieves this
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400731 value.
732 """
733 context = Context(TLSv1_METHOD)
734 context.set_timeout(1234)
735 self.assertEquals(context.get_timeout(), 1234)
736
737
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500738 if not PY3:
739 def test_timeout_long(self):
740 """
741 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
742 `long` as well as int.
743 """
744 context = Context(TLSv1_METHOD)
745 context.set_timeout(long(1234))
746 self.assertEquals(context.get_timeout(), 1234)
747
748
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400749 def test_set_verify_depth_wrong_args(self):
750 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900751 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called with the wrong
752 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400753 """
754 context = Context(TLSv1_METHOD)
755 self.assertRaises(TypeError, context.set_verify_depth)
756 self.assertRaises(TypeError, context.set_verify_depth, None)
757 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
758
759
760 def test_get_verify_depth_wrong_args(self):
761 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900762 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400763 """
764 context = Context(TLSv1_METHOD)
765 self.assertRaises(TypeError, context.get_verify_depth, None)
766
767
768 def test_verify_depth(self):
769 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900770 :py:obj:`Context.set_verify_depth` sets the number of certificates in a chain
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400771 to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900772 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400773 """
774 context = Context(TLSv1_METHOD)
775 context.set_verify_depth(11)
776 self.assertEquals(context.get_verify_depth(), 11)
777
778
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500779 if not PY3:
780 def test_verify_depth_long(self):
781 """
782 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
783 type `long` as well as int.
784 """
785 context = Context(TLSv1_METHOD)
786 context.set_verify_depth(long(11))
787 self.assertEquals(context.get_verify_depth(), 11)
788
789
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400790 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400791 """
792 Write a new private key out to a new file, encrypted using the given
793 passphrase. Return the path to the new file.
794 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400795 key = PKey()
796 key.generate_key(TYPE_RSA, 128)
797 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400798 fObj = open(pemFile, 'w')
799 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
800 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400801 fObj.close()
802 return pemFile
803
804
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400805 def test_set_passwd_cb_wrong_args(self):
806 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900807 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called with the
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400808 wrong arguments or with a non-callable first argument.
809 """
810 context = Context(TLSv1_METHOD)
811 self.assertRaises(TypeError, context.set_passwd_cb)
812 self.assertRaises(TypeError, context.set_passwd_cb, None)
813 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
814
815
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400816 def test_set_passwd_cb(self):
817 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900818 :py:obj:`Context.set_passwd_cb` accepts a callable which will be invoked when
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400819 a private key is loaded from an encrypted PEM.
820 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400821 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400822 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400823 calledWith = []
824 def passphraseCallback(maxlen, verify, extra):
825 calledWith.append((maxlen, verify, extra))
826 return passphrase
827 context = Context(TLSv1_METHOD)
828 context.set_passwd_cb(passphraseCallback)
829 context.use_privatekey_file(pemFile)
830 self.assertTrue(len(calledWith), 1)
831 self.assertTrue(isinstance(calledWith[0][0], int))
832 self.assertTrue(isinstance(calledWith[0][1], int))
833 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400834
835
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400836 def test_passwd_callback_exception(self):
837 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900838 :py:obj:`Context.use_privatekey_file` propagates any exception raised by the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400839 passphrase callback.
840 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400841 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400842 def passphraseCallback(maxlen, verify, extra):
843 raise RuntimeError("Sorry, I am a fail.")
844
845 context = Context(TLSv1_METHOD)
846 context.set_passwd_cb(passphraseCallback)
847 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
848
849
850 def test_passwd_callback_false(self):
851 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900852 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400853 passphrase callback returns a false value.
854 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400855 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400856 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500857 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400858
859 context = Context(TLSv1_METHOD)
860 context.set_passwd_cb(passphraseCallback)
861 self.assertRaises(Error, context.use_privatekey_file, pemFile)
862
863
864 def test_passwd_callback_non_string(self):
865 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900866 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400867 passphrase callback returns a true non-string value.
868 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400869 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400870 def passphraseCallback(maxlen, verify, extra):
871 return 10
872
873 context = Context(TLSv1_METHOD)
874 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800875 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400876
877
878 def test_passwd_callback_too_long(self):
879 """
880 If the passphrase returned by the passphrase callback returns a string
881 longer than the indicated maximum length, it is truncated.
882 """
883 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400884 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400885 pemFile = self._write_encrypted_pem(passphrase)
886 def passphraseCallback(maxlen, verify, extra):
887 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400888 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400889
890 context = Context(TLSv1_METHOD)
891 context.set_passwd_cb(passphraseCallback)
892 # This shall succeed because the truncated result is the correct
893 # passphrase.
894 context.use_privatekey_file(pemFile)
895
896
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400897 def test_set_info_callback(self):
898 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900899 :py:obj:`Context.set_info_callback` accepts a callable which will be invoked
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400900 when certain information about an SSL connection is available.
901 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500902 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400903
904 clientSSL = Connection(Context(TLSv1_METHOD), client)
905 clientSSL.set_connect_state()
906
907 called = []
908 def info(conn, where, ret):
909 called.append((conn, where, ret))
910 context = Context(TLSv1_METHOD)
911 context.set_info_callback(info)
912 context.use_certificate(
913 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
914 context.use_privatekey(
915 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
916
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400917 serverSSL = Connection(context, server)
918 serverSSL.set_accept_state()
919
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500920 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400921
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500922 # The callback must always be called with a Connection instance as the
923 # first argument. It would probably be better to split this into
924 # separate tests for client and server side info callbacks so we could
925 # assert it is called with the right Connection instance. It would
926 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500927 notConnections = [
928 conn for (conn, where, ret) in called
929 if not isinstance(conn, Connection)]
930 self.assertEqual(
931 [], notConnections,
932 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400933
934
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400935 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400936 """
937 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400938 its :py:obj:`load_verify_locations` method with the given arguments.
939 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400940 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500941 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400942
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400943 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400944 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400945 # Require that the server certificate verify properly or the
946 # connection will fail.
947 clientContext.set_verify(
948 VERIFY_PEER,
949 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
950
951 clientSSL = Connection(clientContext, client)
952 clientSSL.set_connect_state()
953
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400954 serverContext = Context(TLSv1_METHOD)
955 serverContext.use_certificate(
956 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
957 serverContext.use_privatekey(
958 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
959
960 serverSSL = Connection(serverContext, server)
961 serverSSL.set_accept_state()
962
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400963 # Without load_verify_locations above, the handshake
964 # will fail:
965 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
966 # 'certificate verify failed')]
967 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400968
969 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400970 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400971
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500972
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400973 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400974 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400975 Verify that if path to a file containing a certificate is passed to
976 ``Context.load_verify_locations`` for the ``cafile`` parameter, that
977 certificate is used as a trust root for the purposes of verifying
978 connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400979 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400980 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400981 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400982 fObj.close()
983
984 self._load_verify_locations_test(cafile)
985
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400986
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400987 def test_load_verify_bytes_cafile(self):
988 """
989 :py:obj:`Context.load_verify_locations` accepts a file name as a
990 ``bytes`` instance and uses the certificates within for verification
991 purposes.
992 """
993 cafile = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
994 self._load_verify_cafile(cafile)
995
996
997 def test_load_verify_unicode_cafile(self):
998 """
999 :py:obj:`Context.load_verify_locations` accepts a file name as a
1000 ``unicode`` instance and uses the certificates within for verification
1001 purposes.
1002 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001003 self._load_verify_cafile(
1004 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
1005 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001006
1007
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001008 def test_load_verify_invalid_file(self):
1009 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001010 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when passed a
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001011 non-existent cafile.
1012 """
1013 clientContext = Context(TLSv1_METHOD)
1014 self.assertRaises(
1015 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001016
1017
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001018 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001019 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001020 Verify that if path to a directory containing certificate files is
1021 passed to ``Context.load_verify_locations`` for the ``capath``
1022 parameter, those certificates are used as trust roots for the purposes
1023 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001024 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001025 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001026 # Hash values computed manually with c_rehash to avoid depending on
1027 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1028 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001029 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001030 cafile = join_bytes_or_unicode(capath, name)
1031 with open(cafile, 'w') as fObj:
1032 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001033
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001034 self._load_verify_locations_test(None, capath)
1035
1036
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001037 def test_load_verify_directory_bytes_capath(self):
1038 """
1039 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1040 ``bytes`` instance and uses the certificates within for verification
1041 purposes.
1042 """
1043 self._load_verify_directory_locations_capath(
1044 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
1045 )
1046
1047
1048 def test_load_verify_directory_unicode_capath(self):
1049 """
1050 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1051 ``unicode`` instance and uses the certificates within for verification
1052 purposes.
1053 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001054 self._load_verify_directory_locations_capath(
1055 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
1056 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001057
1058
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001059 def test_load_verify_locations_wrong_args(self):
1060 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001061 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if called with
1062 the wrong number of arguments or with non-:py:obj:`str` arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001063 """
1064 context = Context(TLSv1_METHOD)
1065 self.assertRaises(TypeError, context.load_verify_locations)
1066 self.assertRaises(TypeError, context.load_verify_locations, object())
1067 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
1068 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
1069
1070
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001071 if platform == "win32":
1072 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001073 "See LP#404343 and LP#404344."
1074 else:
1075 def test_set_default_verify_paths(self):
1076 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001077 :py:obj:`Context.set_default_verify_paths` causes the platform-specific CA
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001078 certificate locations to be used for verification purposes.
1079 """
1080 # Testing this requires a server with a certificate signed by one of
1081 # the CAs in the platform CA location. Getting one of those costs
1082 # money. Fortunately (or unfortunately, depending on your
1083 # perspective), it's easy to think of a public server on the
1084 # internet which has such a certificate. Connecting to the network
1085 # in a unit test is bad, but it's the only way I can think of to
1086 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001087
Alex Gaynorb586da32014-11-15 09:22:21 -08001088 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
1089 context = Context(TLSv1_METHOD)
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001090 context.set_default_verify_paths()
1091 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02001092 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001093 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001094
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001095 client = socket()
1096 client.connect(('verisign.com', 443))
1097 clientSSL = Connection(context, client)
1098 clientSSL.set_connect_state()
1099 clientSSL.do_handshake()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001100 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001101 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001102
1103
1104 def test_set_default_verify_paths_signature(self):
1105 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001106 :py:obj:`Context.set_default_verify_paths` takes no arguments and raises
1107 :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001108 """
1109 context = Context(TLSv1_METHOD)
1110 self.assertRaises(TypeError, context.set_default_verify_paths, None)
1111 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
1112 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001113
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001114
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001115 def test_add_extra_chain_cert_invalid_cert(self):
1116 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001117 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if called with
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001118 other than one argument or if called with an object which is not an
Jonathan Ballet648875f2011-07-16 14:14:58 +09001119 instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001120 """
1121 context = Context(TLSv1_METHOD)
1122 self.assertRaises(TypeError, context.add_extra_chain_cert)
1123 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
1124 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
1125
1126
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001127 def _handshake_test(self, serverContext, clientContext):
1128 """
1129 Verify that a client and server created with the given contexts can
1130 successfully handshake and communicate.
1131 """
1132 serverSocket, clientSocket = socket_pair()
1133
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001134 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001135 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001136
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001137 client = Connection(clientContext, clientSocket)
1138 client.set_connect_state()
1139
1140 # Make them talk to each other.
1141 # self._interactInMemory(client, server)
1142 for i in range(3):
1143 for s in [client, server]:
1144 try:
1145 s.do_handshake()
1146 except WantReadError:
1147 pass
1148
1149
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001150 def test_set_verify_callback_connection_argument(self):
1151 """
1152 The first argument passed to the verify callback is the
1153 :py:class:`Connection` instance for which verification is taking place.
1154 """
1155 serverContext = Context(TLSv1_METHOD)
1156 serverContext.use_privatekey(
1157 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1158 serverContext.use_certificate(
1159 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1160 serverConnection = Connection(serverContext, None)
1161
1162 class VerifyCallback(object):
1163 def callback(self, connection, *args):
1164 self.connection = connection
1165 return 1
1166
1167 verify = VerifyCallback()
1168 clientContext = Context(TLSv1_METHOD)
1169 clientContext.set_verify(VERIFY_PEER, verify.callback)
1170 clientConnection = Connection(clientContext, None)
1171 clientConnection.set_connect_state()
1172
1173 self._handshakeInMemory(clientConnection, serverConnection)
1174
1175 self.assertIdentical(verify.connection, clientConnection)
1176
1177
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001178 def test_set_verify_callback_exception(self):
1179 """
1180 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1181 exception, verification fails and the exception is propagated to the
1182 caller of :py:obj:`Connection.do_handshake`.
1183 """
1184 serverContext = Context(TLSv1_METHOD)
1185 serverContext.use_privatekey(
1186 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1187 serverContext.use_certificate(
1188 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1189
1190 clientContext = Context(TLSv1_METHOD)
1191 def verify_callback(*args):
1192 raise Exception("silly verify failure")
1193 clientContext.set_verify(VERIFY_PEER, verify_callback)
1194
1195 exc = self.assertRaises(
1196 Exception, self._handshake_test, serverContext, clientContext)
1197 self.assertEqual("silly verify failure", str(exc))
1198
1199
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001200 def test_add_extra_chain_cert(self):
1201 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001202 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509` instance to add to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001203 the certificate chain.
1204
Jonathan Ballet648875f2011-07-16 14:14:58 +09001205 See :py:obj:`_create_certificate_chain` for the details of the certificate
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001206 chain tested.
1207
1208 The chain is tested by starting a server with scert and connecting
1209 to it with a client which trusts cacert and requires verification to
1210 succeed.
1211 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001212 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001213 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1214
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001215 # Dump the CA certificate to a file because that's the only way to load
1216 # it as a trusted CA in the client context.
1217 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001218 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001219 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001220 fObj.close()
1221
1222 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001223 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001224 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001225 fObj.close()
1226
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001227 # Create the server context
1228 serverContext = Context(TLSv1_METHOD)
1229 serverContext.use_privatekey(skey)
1230 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001231 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001232 serverContext.add_extra_chain_cert(icert)
1233
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001234 # Create the client
1235 clientContext = Context(TLSv1_METHOD)
1236 clientContext.set_verify(
1237 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001238 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001239
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001240 # Try it out.
1241 self._handshake_test(serverContext, clientContext)
1242
1243
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001244 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001245 """
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001246 Verify that :py:obj:`Context.use_certificate_chain_file` reads a
1247 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001248
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001249 The chain is tested by starting a server with scert and connecting to
1250 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001251 succeed.
1252 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001253 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001254 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1255
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001256 makedirs(certdir)
1257
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001258 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1259 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001260
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001261 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001262 with open(chainFile, 'wb') as fObj:
1263 # Most specific to least general.
1264 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1265 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1266 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1267
1268 with open(caFile, 'w') as fObj:
1269 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001270
1271 serverContext = Context(TLSv1_METHOD)
1272 serverContext.use_certificate_chain_file(chainFile)
1273 serverContext.use_privatekey(skey)
1274
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001275 clientContext = Context(TLSv1_METHOD)
1276 clientContext.set_verify(
1277 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001278 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001279
1280 self._handshake_test(serverContext, clientContext)
1281
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001282
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001283 def test_use_certificate_chain_file_bytes(self):
1284 """
1285 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1286 an instance of ``bytes``) to specify additional certificates to use to
1287 construct and verify a trust chain.
1288 """
1289 self._use_certificate_chain_file_test(
1290 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
1291 )
1292
1293
1294 def test_use_certificate_chain_file_unicode(self):
1295 """
1296 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1297 an instance of ``unicode``) to specify additional certificates to use
1298 to construct and verify a trust chain.
1299 """
1300 self._use_certificate_chain_file_test(
1301 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
1302 )
1303
1304
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001305 def test_use_certificate_chain_file_wrong_args(self):
1306 """
1307 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1308 if passed zero or more than one argument or when passed a non-byte
1309 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error` when
1310 passed a bad chain file name (for example, the name of a file which does
1311 not exist).
1312 """
1313 context = Context(TLSv1_METHOD)
1314 self.assertRaises(TypeError, context.use_certificate_chain_file)
1315 self.assertRaises(TypeError, context.use_certificate_chain_file, object())
1316 self.assertRaises(TypeError, context.use_certificate_chain_file, b"foo", object())
1317
1318 self.assertRaises(Error, context.use_certificate_chain_file, self.mktemp())
1319
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001320 # XXX load_client_ca
1321 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001322
1323 def test_get_verify_mode_wrong_args(self):
1324 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001325 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001326 arguments.
1327 """
1328 context = Context(TLSv1_METHOD)
1329 self.assertRaises(TypeError, context.get_verify_mode, None)
1330
1331
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001332 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001333 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001334 :py:obj:`Context.get_verify_mode` returns the verify mode flags previously
1335 passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001336 """
1337 context = Context(TLSv1_METHOD)
1338 self.assertEquals(context.get_verify_mode(), 0)
1339 context.set_verify(
1340 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1341 self.assertEquals(
1342 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1343
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001344
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001345 if not PY3:
1346 def test_set_verify_mode_long(self):
1347 """
1348 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1349 type :py:obj:`long` as well as :py:obj:`int`.
1350 """
1351 context = Context(TLSv1_METHOD)
1352 self.assertEquals(context.get_verify_mode(), 0)
1353 context.set_verify(
1354 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None)
1355 self.assertEquals(
1356 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1357
1358
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001359 def test_load_tmp_dh_wrong_args(self):
1360 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001361 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
1362 number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001363 """
1364 context = Context(TLSv1_METHOD)
1365 self.assertRaises(TypeError, context.load_tmp_dh)
1366 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1367 self.assertRaises(TypeError, context.load_tmp_dh, object())
1368
1369
1370 def test_load_tmp_dh_missing_file(self):
1371 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001372 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the specified file
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001373 does not exist.
1374 """
1375 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001376 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001377
1378
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001379 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001380 """
1381 Verify that calling ``Context.load_tmp_dh`` with the given filename
1382 does not raise an exception.
1383 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001384 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001385 with open(dhfilename, "w") as dhfile:
1386 dhfile.write(dhparam)
1387
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001388 context.load_tmp_dh(dhfilename)
1389 # XXX What should I assert here? -exarkun
1390
1391
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001392 def test_load_tmp_dh_bytes(self):
1393 """
1394 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1395 specified file (given as ``bytes``).
1396 """
1397 self._load_tmp_dh_test(
1398 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
1399 )
1400
1401
1402 def test_load_tmp_dh_unicode(self):
1403 """
1404 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1405 specified file (given as ``unicode``).
1406 """
1407 self._load_tmp_dh_test(
1408 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
1409 )
1410
1411
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001412 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001413 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001414 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001415 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001416 """
1417 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001418 for curve in get_elliptic_curves():
1419 # The only easily "assertable" thing is that it does not raise an
1420 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001421 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001422
1423
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001424 def test_set_cipher_list_bytes(self):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001425 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001426 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
1427 ciphers which connections created with the context object will be able
1428 to choose from.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001429 """
1430 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001431 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001432 conn = Connection(context, None)
1433 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001434
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001435
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001436 def test_set_cipher_list_text(self):
1437 """
1438 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
1439 the ciphers which connections created with the context object will be
1440 able to choose from.
1441 """
1442 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -05001443 context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001444 conn = Connection(context, None)
1445 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
1446
1447
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001448 def test_set_cipher_list_wrong_args(self):
1449 """
Jean-Paul Calderone17044832014-01-18 10:20:11 -05001450 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
1451 passed zero arguments or more than one argument or when passed a
1452 non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001453 passed an incorrect cipher list string.
1454 """
1455 context = Context(TLSv1_METHOD)
1456 self.assertRaises(TypeError, context.set_cipher_list)
1457 self.assertRaises(TypeError, context.set_cipher_list, object())
1458 self.assertRaises(TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object())
1459
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001460 self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001461
1462
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001463 def test_set_session_cache_mode_wrong_args(self):
1464 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001465 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1466 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001467 """
1468 context = Context(TLSv1_METHOD)
1469 self.assertRaises(TypeError, context.set_session_cache_mode)
1470 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1471
1472
1473 def test_get_session_cache_mode_wrong_args(self):
1474 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001475 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1476 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001477 """
1478 context = Context(TLSv1_METHOD)
1479 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1480
1481
1482 def test_session_cache_mode(self):
1483 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001484 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1485 cached. The setting can be retrieved via
1486 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001487 """
1488 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001489 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001490 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1491 self.assertEqual(SESS_CACHE_OFF, off)
1492 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1493
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001494 if not PY3:
1495 def test_session_cache_mode_long(self):
1496 """
1497 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1498 of type :py:obj:`long` as well as :py:obj:`int`.
1499 """
1500 context = Context(TLSv1_METHOD)
1501 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1502 self.assertEqual(
1503 SESS_CACHE_BOTH, context.get_session_cache_mode())
1504
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001505
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001506 def test_get_cert_store(self):
1507 """
1508 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store` instance.
1509 """
1510 context = Context(TLSv1_METHOD)
1511 store = context.get_cert_store()
1512 self.assertIsInstance(store, X509Store)
1513
1514
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001515
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001516class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1517 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001518 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
1519 :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001520 """
1521 def test_wrong_args(self):
1522 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001523 :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001524 with other than one argument.
1525 """
1526 context = Context(TLSv1_METHOD)
1527 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1528 self.assertRaises(
1529 TypeError, context.set_tlsext_servername_callback, 1, 2)
1530
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001531
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001532 def test_old_callback_forgotten(self):
1533 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001534 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001535 callback, the one it replaces is dereferenced.
1536 """
1537 def callback(connection):
1538 pass
1539
1540 def replacement(connection):
1541 pass
1542
1543 context = Context(TLSv1_METHOD)
1544 context.set_tlsext_servername_callback(callback)
1545
1546 tracker = ref(callback)
1547 del callback
1548
1549 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001550
1551 # One run of the garbage collector happens to work on CPython. PyPy
1552 # doesn't collect the underlying object until a second run for whatever
1553 # reason. That's fine, it still demonstrates our code has properly
1554 # dropped the reference.
1555 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001556 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001557
1558 callback = tracker()
1559 if callback is not None:
1560 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001561 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001562 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001563
1564
1565 def test_no_servername(self):
1566 """
1567 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001568 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
1569 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001570 """
1571 args = []
1572 def servername(conn):
1573 args.append((conn, conn.get_servername()))
1574 context = Context(TLSv1_METHOD)
1575 context.set_tlsext_servername_callback(servername)
1576
1577 # Lose our reference to it. The Context is responsible for keeping it
1578 # alive now.
1579 del servername
1580 collect()
1581
1582 # Necessary to actually accept the connection
1583 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1584 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1585
1586 # Do a little connection to trigger the logic
1587 server = Connection(context, None)
1588 server.set_accept_state()
1589
1590 client = Connection(Context(TLSv1_METHOD), None)
1591 client.set_connect_state()
1592
1593 self._interactInMemory(server, client)
1594
1595 self.assertEqual([(server, None)], args)
1596
1597
1598 def test_servername(self):
1599 """
1600 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +09001601 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
1602 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001603 """
1604 args = []
1605 def servername(conn):
1606 args.append((conn, conn.get_servername()))
1607 context = Context(TLSv1_METHOD)
1608 context.set_tlsext_servername_callback(servername)
1609
1610 # Necessary to actually accept the connection
1611 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1612 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1613
1614 # Do a little connection to trigger the logic
1615 server = Connection(context, None)
1616 server.set_accept_state()
1617
1618 client = Connection(Context(TLSv1_METHOD), None)
1619 client.set_connect_state()
1620 client.set_tlsext_host_name(b("foo1.example.com"))
1621
1622 self._interactInMemory(server, client)
1623
1624 self.assertEqual([(server, b("foo1.example.com"))], args)
1625
1626
Cory Benfield84a121e2014-03-31 20:30:25 +01001627class NextProtoNegotiationTests(TestCase, _LoopbackMixin):
1628 """
1629 Test for Next Protocol Negotiation in PyOpenSSL.
1630 """
Cory Benfieldba1820d2015-04-13 17:39:12 -04001631 if _lib.Cryptography_HAS_NEXTPROTONEG:
1632 def test_npn_success(self):
1633 """
1634 Tests that clients and servers that agree on the negotiated next
1635 protocol can correct establish a connection, and that the agreed
1636 protocol is reported by the connections.
1637 """
1638 advertise_args = []
1639 select_args = []
1640 def advertise(conn):
1641 advertise_args.append((conn,))
1642 return [b'http/1.1', b'spdy/2']
1643 def select(conn, options):
1644 select_args.append((conn, options))
1645 return b'spdy/2'
Cory Benfield84a121e2014-03-31 20:30:25 +01001646
Cory Benfieldba1820d2015-04-13 17:39:12 -04001647 server_context = Context(TLSv1_METHOD)
1648 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001649
Cory Benfieldba1820d2015-04-13 17:39:12 -04001650 client_context = Context(TLSv1_METHOD)
1651 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001652
Cory Benfieldba1820d2015-04-13 17:39:12 -04001653 # Necessary to actually accept the connection
1654 server_context.use_privatekey(
1655 load_privatekey(FILETYPE_PEM, server_key_pem))
1656 server_context.use_certificate(
1657 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001658
Cory Benfieldba1820d2015-04-13 17:39:12 -04001659 # Do a little connection to trigger the logic
1660 server = Connection(server_context, None)
1661 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001662
Cory Benfieldba1820d2015-04-13 17:39:12 -04001663 client = Connection(client_context, None)
1664 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001665
Cory Benfieldba1820d2015-04-13 17:39:12 -04001666 self._interactInMemory(server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001667
Cory Benfieldba1820d2015-04-13 17:39:12 -04001668 self.assertEqual([(server,)], advertise_args)
1669 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001670
Cory Benfieldba1820d2015-04-13 17:39:12 -04001671 self.assertEqual(server.get_next_proto_negotiated(), b'spdy/2')
1672 self.assertEqual(client.get_next_proto_negotiated(), b'spdy/2')
Cory Benfield84a121e2014-03-31 20:30:25 +01001673
1674
Cory Benfieldba1820d2015-04-13 17:39:12 -04001675 def test_npn_client_fail(self):
1676 """
1677 Tests that when clients and servers cannot agree on what protocol
1678 to use next that the TLS connection does not get established.
1679 """
1680 advertise_args = []
1681 select_args = []
1682 def advertise(conn):
1683 advertise_args.append((conn,))
1684 return [b'http/1.1', b'spdy/2']
1685 def select(conn, options):
1686 select_args.append((conn, options))
1687 return b''
Cory Benfield84a121e2014-03-31 20:30:25 +01001688
Cory Benfieldba1820d2015-04-13 17:39:12 -04001689 server_context = Context(TLSv1_METHOD)
1690 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001691
Cory Benfieldba1820d2015-04-13 17:39:12 -04001692 client_context = Context(TLSv1_METHOD)
1693 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001694
Cory Benfieldba1820d2015-04-13 17:39:12 -04001695 # Necessary to actually accept the connection
1696 server_context.use_privatekey(
1697 load_privatekey(FILETYPE_PEM, server_key_pem))
1698 server_context.use_certificate(
1699 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001700
Cory Benfieldba1820d2015-04-13 17:39:12 -04001701 # Do a little connection to trigger the logic
1702 server = Connection(server_context, None)
1703 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001704
Cory Benfieldba1820d2015-04-13 17:39:12 -04001705 client = Connection(client_context, None)
1706 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001707
Cory Benfieldba1820d2015-04-13 17:39:12 -04001708 # If the client doesn't return anything, the connection will fail.
1709 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001710
Cory Benfieldba1820d2015-04-13 17:39:12 -04001711 self.assertEqual([(server,)], advertise_args)
1712 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001713
1714
Cory Benfieldba1820d2015-04-13 17:39:12 -04001715 def test_npn_select_error(self):
1716 """
1717 Test that we can handle exceptions in the select callback. If
1718 select fails it should be fatal to the connection.
1719 """
1720 advertise_args = []
1721 def advertise(conn):
1722 advertise_args.append((conn,))
1723 return [b'http/1.1', b'spdy/2']
1724 def select(conn, options):
1725 raise TypeError
Cory Benfield0ea76e72015-03-22 09:05:28 +00001726
Cory Benfieldba1820d2015-04-13 17:39:12 -04001727 server_context = Context(TLSv1_METHOD)
1728 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001729
Cory Benfieldba1820d2015-04-13 17:39:12 -04001730 client_context = Context(TLSv1_METHOD)
1731 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001732
Cory Benfieldba1820d2015-04-13 17:39:12 -04001733 # Necessary to actually accept the connection
1734 server_context.use_privatekey(
1735 load_privatekey(FILETYPE_PEM, server_key_pem))
1736 server_context.use_certificate(
1737 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001738
Cory Benfieldba1820d2015-04-13 17:39:12 -04001739 # Do a little connection to trigger the logic
1740 server = Connection(server_context, None)
1741 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001742
Cory Benfieldba1820d2015-04-13 17:39:12 -04001743 client = Connection(client_context, None)
1744 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001745
Cory Benfieldba1820d2015-04-13 17:39:12 -04001746 # If the callback throws an exception it should be raised here.
1747 self.assertRaises(
1748 TypeError, self._interactInMemory, server, client
1749 )
1750 self.assertEqual([(server,)], advertise_args)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001751
1752
Cory Benfieldba1820d2015-04-13 17:39:12 -04001753 def test_npn_advertise_error(self):
1754 """
1755 Test that we can handle exceptions in the advertise callback. If
1756 advertise fails no NPN is advertised to the client.
1757 """
1758 select_args = []
1759 def advertise(conn):
1760 raise TypeError
1761 def select(conn, options):
1762 select_args.append((conn, options))
1763 return b''
Cory Benfield0ea76e72015-03-22 09:05:28 +00001764
Cory Benfieldba1820d2015-04-13 17:39:12 -04001765 server_context = Context(TLSv1_METHOD)
1766 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001767
Cory Benfieldba1820d2015-04-13 17:39:12 -04001768 client_context = Context(TLSv1_METHOD)
1769 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001770
Cory Benfieldba1820d2015-04-13 17:39:12 -04001771 # Necessary to actually accept the connection
1772 server_context.use_privatekey(
1773 load_privatekey(FILETYPE_PEM, server_key_pem))
1774 server_context.use_certificate(
1775 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001776
Cory Benfieldba1820d2015-04-13 17:39:12 -04001777 # Do a little connection to trigger the logic
1778 server = Connection(server_context, None)
1779 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001780
Cory Benfieldba1820d2015-04-13 17:39:12 -04001781 client = Connection(client_context, None)
1782 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001783
Cory Benfieldba1820d2015-04-13 17:39:12 -04001784 # If the client doesn't return anything, the connection will fail.
1785 self.assertRaises(
1786 TypeError, self._interactInMemory, server, client
1787 )
1788 self.assertEqual([], select_args)
1789
1790 else:
1791 # No NPN.
1792 def test_npn_not_implemented(self):
1793 # Test the context methods first.
1794 context = Context(TLSv1_METHOD)
1795 fail_methods = [
1796 context.set_npn_advertise_callback,
1797 context.set_npn_select_callback,
1798 ]
1799 for method in fail_methods:
1800 self.assertRaises(
1801 NotImplementedError, method, None
1802 )
1803
1804 # Now test a connection.
1805 conn = Connection(context)
1806 fail_methods = [
1807 conn.get_next_proto_negotiated,
1808 ]
1809 for method in fail_methods:
1810 self.assertRaises(NotImplementedError, method)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001811
1812
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001813
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001814class SessionTests(TestCase):
1815 """
1816 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1817 """
1818 def test_construction(self):
1819 """
1820 :py:class:`Session` can be constructed with no arguments, creating a new
1821 instance of that type.
1822 """
1823 new_session = Session()
1824 self.assertTrue(isinstance(new_session, Session))
1825
1826
1827 def test_construction_wrong_args(self):
1828 """
1829 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
1830 is raised.
1831 """
1832 self.assertRaises(TypeError, Session, 123)
1833 self.assertRaises(TypeError, Session, "hello")
1834 self.assertRaises(TypeError, Session, object())
1835
1836
1837
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001838class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05001839 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001840 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001841 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001842 # XXX get_peer_certificate -> None
1843 # XXX sock_shutdown
1844 # XXX master_key -> TypeError
1845 # XXX server_random -> TypeError
1846 # XXX state_string
1847 # XXX connect -> TypeError
1848 # XXX connect_ex -> TypeError
1849 # XXX set_connect_state -> TypeError
1850 # XXX set_accept_state -> TypeError
1851 # XXX renegotiate_pending
1852 # XXX do_handshake -> TypeError
1853 # XXX bio_read -> TypeError
1854 # XXX recv -> TypeError
1855 # XXX send -> TypeError
1856 # XXX bio_write -> TypeError
1857
Rick Deane15b1472009-07-09 15:53:42 -05001858 def test_type(self):
1859 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001860 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001861 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05001862 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001863 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05001864 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001865 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05001866
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001867
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001868 def test_get_context(self):
1869 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001870 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
1871 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001872 """
1873 context = Context(TLSv1_METHOD)
1874 connection = Connection(context, None)
1875 self.assertIdentical(connection.get_context(), context)
1876
1877
1878 def test_get_context_wrong_args(self):
1879 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001880 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001881 arguments.
1882 """
1883 connection = Connection(Context(TLSv1_METHOD), None)
1884 self.assertRaises(TypeError, connection.get_context, None)
1885
1886
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001887 def test_set_context_wrong_args(self):
1888 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001889 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
1890 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001891 than 1.
1892 """
1893 ctx = Context(TLSv1_METHOD)
1894 connection = Connection(ctx, None)
1895 self.assertRaises(TypeError, connection.set_context)
1896 self.assertRaises(TypeError, connection.set_context, object())
1897 self.assertRaises(TypeError, connection.set_context, "hello")
1898 self.assertRaises(TypeError, connection.set_context, 1)
1899 self.assertRaises(TypeError, connection.set_context, 1, 2)
1900 self.assertRaises(
1901 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
1902 self.assertIdentical(ctx, connection.get_context())
1903
1904
1905 def test_set_context(self):
1906 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001907 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001908 for the connection.
1909 """
1910 original = Context(SSLv23_METHOD)
1911 replacement = Context(TLSv1_METHOD)
1912 connection = Connection(original, None)
1913 connection.set_context(replacement)
1914 self.assertIdentical(replacement, connection.get_context())
1915 # Lose our references to the contexts, just in case the Connection isn't
1916 # properly managing its own contributions to their reference counts.
1917 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001918 collect()
1919
1920
1921 def test_set_tlsext_host_name_wrong_args(self):
1922 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001923 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001924 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09001925 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001926 """
1927 conn = Connection(Context(TLSv1_METHOD), None)
1928 self.assertRaises(TypeError, conn.set_tlsext_host_name)
1929 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
1930 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
1931 self.assertRaises(
1932 TypeError, conn.set_tlsext_host_name, b("with\0null"))
1933
1934 if version_info >= (3,):
1935 # On Python 3.x, don't accidentally implicitly convert from text.
1936 self.assertRaises(
1937 TypeError,
1938 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001939
1940
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001941 def test_get_servername_wrong_args(self):
1942 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001943 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001944 arguments.
1945 """
1946 connection = Connection(Context(TLSv1_METHOD), None)
1947 self.assertRaises(TypeError, connection.get_servername, object())
1948 self.assertRaises(TypeError, connection.get_servername, 1)
1949 self.assertRaises(TypeError, connection.get_servername, "hello")
1950
1951
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001952 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001953 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001954 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001955 immediate read.
1956 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001957 connection = Connection(Context(TLSv1_METHOD), None)
1958 self.assertEquals(connection.pending(), 0)
1959
1960
1961 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001962 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001963 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001964 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001965 connection = Connection(Context(TLSv1_METHOD), None)
1966 self.assertRaises(TypeError, connection.pending, None)
1967
1968
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001969 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001970 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001971 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001972 argument or with the wrong number of arguments.
1973 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001974 connection = Connection(Context(TLSv1_METHOD), socket())
1975 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001976 self.assertRaises(TypeError, connection.connect)
1977 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001978
1979
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001980 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001981 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001982 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001983 connect method raises it.
1984 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001985 client = socket()
1986 context = Context(TLSv1_METHOD)
1987 clientSSL = Connection(context, client)
1988 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04001989 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001990
1991
1992 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001993 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001994 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001995 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001996 port = socket()
1997 port.bind(('', 0))
1998 port.listen(3)
1999
2000 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002001 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2002 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002003
2004
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002005 if platform == "darwin":
2006 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2007 else:
2008 def test_connect_ex(self):
2009 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002010 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002011 errno instead of raising an exception.
2012 """
2013 port = socket()
2014 port.bind(('', 0))
2015 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002016
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04002017 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2018 clientSSL.setblocking(False)
2019 result = clientSSL.connect_ex(port.getsockname())
2020 expected = (EINPROGRESS, EWOULDBLOCK)
2021 self.assertTrue(
2022 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002023
2024
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002025 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002026 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002027 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002028 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002029 connection = Connection(Context(TLSv1_METHOD), socket())
2030 self.assertRaises(TypeError, connection.accept, None)
2031
2032
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002033 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002034 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002035 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
2036 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002037 connection originated from.
2038 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002039 ctx = Context(TLSv1_METHOD)
2040 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2041 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002042 port = socket()
2043 portSSL = Connection(ctx, port)
2044 portSSL.bind(('', 0))
2045 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002046
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002047 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002048
2049 # Calling portSSL.getsockname() here to get the server IP address sounds
2050 # great, but frequently fails on Windows.
2051 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002052
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002053 serverSSL, address = portSSL.accept()
2054
2055 self.assertTrue(isinstance(serverSSL, Connection))
2056 self.assertIdentical(serverSSL.get_context(), ctx)
2057 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002058
2059
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002060 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002061 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002062 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002063 number of arguments or with arguments other than integers.
2064 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002065 connection = Connection(Context(TLSv1_METHOD), None)
2066 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04002067 self.assertRaises(TypeError, connection.get_shutdown, None)
2068 self.assertRaises(TypeError, connection.set_shutdown)
2069 self.assertRaises(TypeError, connection.set_shutdown, None)
2070 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002071
2072
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002073 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002074 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002075 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002076 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002077 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002078 self.assertFalse(server.shutdown())
2079 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002080 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002081 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
2082 client.shutdown()
2083 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
2084 self.assertRaises(ZeroReturnError, server.recv, 1024)
2085 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002086
2087
Paul Aurichc85e0862015-01-08 08:34:33 -08002088 def test_shutdown_closed(self):
2089 """
2090 If the underlying socket is closed, :py:obj:`Connection.shutdown` propagates the
2091 write error from the low level write call.
2092 """
2093 server, client = self._loopback()
2094 server.sock_shutdown(2)
2095 exc = self.assertRaises(SysCallError, server.shutdown)
2096 if platform == "win32":
2097 self.assertEqual(exc.args[0], ESHUTDOWN)
2098 else:
2099 self.assertEqual(exc.args[0], EPIPE)
2100
2101
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002102 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002103 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002104 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002105 process.
2106 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002107 connection = Connection(Context(TLSv1_METHOD), socket())
2108 connection.set_shutdown(RECEIVED_SHUTDOWN)
2109 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2110
2111
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002112 if not PY3:
2113 def test_set_shutdown_long(self):
2114 """
2115 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
2116 of type :py:obj:`long` as well as :py:obj:`int`.
2117 """
2118 connection = Connection(Context(TLSv1_METHOD), socket())
2119 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
2120 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2121
2122
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002123 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002124 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002125 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
2126 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002127 with any arguments.
2128 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002129 conn = Connection(Context(TLSv1_METHOD), None)
2130 self.assertRaises(TypeError, conn.get_app_data, None)
2131 self.assertRaises(TypeError, conn.set_app_data)
2132 self.assertRaises(TypeError, conn.set_app_data, None, None)
2133
2134
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002135 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002136 """
2137 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002138 :py:obj:`Connection.set_app_data` and later retrieved with
2139 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002140 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002141 conn = Connection(Context(TLSv1_METHOD), None)
2142 app_data = object()
2143 conn.set_app_data(app_data)
2144 self.assertIdentical(conn.get_app_data(), app_data)
2145
2146
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002147 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002148 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002149 :py:obj:`Connection.makefile` is not implemented and calling that method raises
2150 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002151 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002152 conn = Connection(Context(TLSv1_METHOD), None)
2153 self.assertRaises(NotImplementedError, conn.makefile)
2154
2155
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002156 def test_get_peer_cert_chain_wrong_args(self):
2157 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002158 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002159 arguments.
2160 """
2161 conn = Connection(Context(TLSv1_METHOD), None)
2162 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
2163 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
2164 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
2165 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
2166
2167
2168 def test_get_peer_cert_chain(self):
2169 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002170 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002171 the connected server returned for the certification verification.
2172 """
2173 chain = _create_certificate_chain()
2174 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2175
2176 serverContext = Context(TLSv1_METHOD)
2177 serverContext.use_privatekey(skey)
2178 serverContext.use_certificate(scert)
2179 serverContext.add_extra_chain_cert(icert)
2180 serverContext.add_extra_chain_cert(cacert)
2181 server = Connection(serverContext, None)
2182 server.set_accept_state()
2183
2184 # Create the client
2185 clientContext = Context(TLSv1_METHOD)
2186 clientContext.set_verify(VERIFY_NONE, verify_cb)
2187 client = Connection(clientContext, None)
2188 client.set_connect_state()
2189
2190 self._interactInMemory(client, server)
2191
2192 chain = client.get_peer_cert_chain()
2193 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002194 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002195 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002196 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002197 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002198 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002199 "Authority Certificate", chain[2].get_subject().CN)
2200
2201
2202 def test_get_peer_cert_chain_none(self):
2203 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002204 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002205 certificate chain.
2206 """
2207 ctx = Context(TLSv1_METHOD)
2208 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2209 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2210 server = Connection(ctx, None)
2211 server.set_accept_state()
2212 client = Connection(Context(TLSv1_METHOD), None)
2213 client.set_connect_state()
2214 self._interactInMemory(client, server)
2215 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002216
2217
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002218 def test_get_session_wrong_args(self):
2219 """
2220 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
2221 with any arguments.
2222 """
2223 ctx = Context(TLSv1_METHOD)
2224 server = Connection(ctx, None)
2225 self.assertRaises(TypeError, server.get_session, 123)
2226 self.assertRaises(TypeError, server.get_session, "hello")
2227 self.assertRaises(TypeError, server.get_session, object())
2228
2229
2230 def test_get_session_unconnected(self):
2231 """
2232 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
2233 an object which has not been connected.
2234 """
2235 ctx = Context(TLSv1_METHOD)
2236 server = Connection(ctx, None)
2237 session = server.get_session()
2238 self.assertIdentical(None, session)
2239
2240
2241 def test_server_get_session(self):
2242 """
2243 On the server side of a connection, :py:obj:`Connection.get_session`
2244 returns a :py:class:`Session` instance representing the SSL session for
2245 that connection.
2246 """
2247 server, client = self._loopback()
2248 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002249 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002250
2251
2252 def test_client_get_session(self):
2253 """
2254 On the client side of a connection, :py:obj:`Connection.get_session`
2255 returns a :py:class:`Session` instance representing the SSL session for
2256 that connection.
2257 """
2258 server, client = self._loopback()
2259 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002260 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002261
2262
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002263 def test_set_session_wrong_args(self):
2264 """
2265 If called with an object that is not an instance of :py:class:`Session`,
2266 or with other than one argument, :py:obj:`Connection.set_session` raises
2267 :py:obj:`TypeError`.
2268 """
2269 ctx = Context(TLSv1_METHOD)
2270 connection = Connection(ctx, None)
2271 self.assertRaises(TypeError, connection.set_session)
2272 self.assertRaises(TypeError, connection.set_session, 123)
2273 self.assertRaises(TypeError, connection.set_session, "hello")
2274 self.assertRaises(TypeError, connection.set_session, object())
2275 self.assertRaises(
2276 TypeError, connection.set_session, Session(), Session())
2277
2278
2279 def test_client_set_session(self):
2280 """
2281 :py:obj:`Connection.set_session`, when used prior to a connection being
2282 established, accepts a :py:class:`Session` instance and causes an
2283 attempt to re-use the session it represents when the SSL handshake is
2284 performed.
2285 """
2286 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2287 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2288 ctx = Context(TLSv1_METHOD)
2289 ctx.use_privatekey(key)
2290 ctx.use_certificate(cert)
2291 ctx.set_session_id("unity-test")
2292
2293 def makeServer(socket):
2294 server = Connection(ctx, socket)
2295 server.set_accept_state()
2296 return server
2297
2298 originalServer, originalClient = self._loopback(
2299 serverFactory=makeServer)
2300 originalSession = originalClient.get_session()
2301
2302 def makeClient(socket):
2303 client = self._loopbackClientFactory(socket)
2304 client.set_session(originalSession)
2305 return client
2306 resumedServer, resumedClient = self._loopback(
2307 serverFactory=makeServer,
2308 clientFactory=makeClient)
2309
2310 # This is a proxy: in general, we have no access to any unique
2311 # identifier for the session (new enough versions of OpenSSL expose a
2312 # hash which could be usable, but "new enough" is very, very new).
2313 # Instead, exploit the fact that the master key is re-used if the
2314 # session is re-used. As long as the master key for the two connections
2315 # is the same, the session was re-used!
2316 self.assertEqual(
2317 originalServer.master_key(), resumedServer.master_key())
2318
2319
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002320 def test_set_session_wrong_method(self):
2321 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002322 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
2323 instance associated with a context using a different SSL method than the
2324 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
2325 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002326 """
2327 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2328 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2329 ctx = Context(TLSv1_METHOD)
2330 ctx.use_privatekey(key)
2331 ctx.use_certificate(cert)
2332 ctx.set_session_id("unity-test")
2333
2334 def makeServer(socket):
2335 server = Connection(ctx, socket)
2336 server.set_accept_state()
2337 return server
2338
2339 originalServer, originalClient = self._loopback(
2340 serverFactory=makeServer)
2341 originalSession = originalClient.get_session()
2342
2343 def makeClient(socket):
2344 # Intentionally use a different, incompatible method here.
2345 client = Connection(Context(SSLv3_METHOD), socket)
2346 client.set_connect_state()
2347 client.set_session(originalSession)
2348 return client
2349
2350 self.assertRaises(
2351 Error,
2352 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2353
2354
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002355 def test_wantWriteError(self):
2356 """
2357 :py:obj:`Connection` methods which generate output raise
2358 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2359 fail indicating a should-write state.
2360 """
2361 client_socket, server_socket = socket_pair()
2362 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002363 # anything. Only write a single byte at a time so we can be sure we
2364 # completely fill the buffer. Even though the socket API is allowed to
2365 # signal a short write via its return value it seems this doesn't
2366 # always happen on all platforms (FreeBSD and OS X particular) for the
2367 # very last bit of available buffer space.
2368 msg = b"x"
2369 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002370 try:
2371 client_socket.send(msg)
2372 except error as e:
2373 if e.errno == EWOULDBLOCK:
2374 break
2375 raise
2376 else:
2377 self.fail(
2378 "Failed to fill socket buffer, cannot test BIO want write")
2379
2380 ctx = Context(TLSv1_METHOD)
2381 conn = Connection(ctx, client_socket)
2382 # Client's speak first, so make it an SSL client
2383 conn.set_connect_state()
2384 self.assertRaises(WantWriteError, conn.do_handshake)
2385
2386 # XXX want_read
2387
Fedor Brunner416f4a12014-03-28 13:18:38 +01002388 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002389 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002390 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2391 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002392 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002393 ctx = Context(TLSv1_METHOD)
2394 connection = Connection(ctx, None)
2395 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002396
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002397
Fedor Brunner416f4a12014-03-28 13:18:38 +01002398 def test_get_peer_finished_before_connect(self):
2399 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002400 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2401 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002402 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002403 ctx = Context(TLSv1_METHOD)
2404 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002405 self.assertEqual(connection.get_peer_finished(), None)
2406
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002407
Fedor Brunner416f4a12014-03-28 13:18:38 +01002408 def test_get_finished(self):
2409 """
2410 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002411 message send from client, or server. Finished messages are send during
2412 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002413 """
2414
Fedor Brunner5747b932014-03-05 14:22:34 +01002415 server, client = self._loopback()
2416
2417 self.assertNotEqual(server.get_finished(), None)
2418 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002419
Jean-Paul Calderoned979f232014-03-30 11:58:00 -04002420
Fedor Brunner416f4a12014-03-28 13:18:38 +01002421 def test_get_peer_finished(self):
2422 """
2423 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002424 message received from client, or server. Finished messages are send
2425 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002426 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002427 server, client = self._loopback()
2428
2429 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002430 self.assertTrue(len(server.get_peer_finished()) > 0)
2431
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002432
Fedor Brunner416f4a12014-03-28 13:18:38 +01002433 def test_tls_finished_message_symmetry(self):
2434 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002435 The TLS Finished message send by server must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002436 received by client.
2437
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002438 The TLS Finished message send by client must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002439 received by server.
2440 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002441 server, client = self._loopback()
2442
Fedor Brunner5747b932014-03-05 14:22:34 +01002443 self.assertEqual(server.get_finished(), client.get_peer_finished())
2444 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002445
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002446
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002447 def test_get_cipher_name_before_connect(self):
2448 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002449 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2450 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002451 """
2452 ctx = Context(TLSv1_METHOD)
2453 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002454 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002455
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002456
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002457 def test_get_cipher_name(self):
2458 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002459 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2460 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002461 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002462 server, client = self._loopback()
2463 server_cipher_name, client_cipher_name = \
2464 server.get_cipher_name(), client.get_cipher_name()
2465
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002466 self.assertIsInstance(server_cipher_name, text_type)
2467 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002468
2469 self.assertEqual(server_cipher_name, client_cipher_name)
2470
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002471
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002472 def test_get_cipher_version_before_connect(self):
2473 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002474 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2475 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002476 """
2477 ctx = Context(TLSv1_METHOD)
2478 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002479 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002480
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002481
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002482 def test_get_cipher_version(self):
2483 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002484 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2485 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002486 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002487 server, client = self._loopback()
2488 server_cipher_version, client_cipher_version = \
2489 server.get_cipher_version(), client.get_cipher_version()
2490
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002491 self.assertIsInstance(server_cipher_version, text_type)
2492 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002493
2494 self.assertEqual(server_cipher_version, client_cipher_version)
2495
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002496
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002497 def test_get_cipher_bits_before_connect(self):
2498 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002499 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2500 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002501 """
2502 ctx = Context(TLSv1_METHOD)
2503 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002504 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002505
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002506
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002507 def test_get_cipher_bits(self):
2508 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002509 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2510 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002511 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002512 server, client = self._loopback()
2513 server_cipher_bits, client_cipher_bits = \
2514 server.get_cipher_bits(), client.get_cipher_bits()
2515
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002516 self.assertIsInstance(server_cipher_bits, int)
2517 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002518
2519 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002520
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002521
2522
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002523class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002524 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002525 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002526 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002527 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002528 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002529 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002530 arguments.
2531 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002532 connection = Connection(Context(TLSv1_METHOD), None)
2533 self.assertRaises(TypeError, connection.get_cipher_list, None)
2534
2535
2536 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002537 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002538 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2539 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002540 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002541 connection = Connection(Context(TLSv1_METHOD), None)
2542 ciphers = connection.get_cipher_list()
2543 self.assertTrue(isinstance(ciphers, list))
2544 for cipher in ciphers:
2545 self.assertTrue(isinstance(cipher, str))
2546
2547
2548
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002549class ConnectionSendTests(TestCase, _LoopbackMixin):
2550 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002551 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002552 """
2553 def test_wrong_args(self):
2554 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002555 When called with arguments other than string argument for its first
2556 parameter or more than two arguments, :py:obj:`Connection.send` raises
2557 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002558 """
2559 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002560 self.assertRaises(TypeError, connection.send)
2561 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002562 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002563
2564
2565 def test_short_bytes(self):
2566 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002567 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002568 and returns the number of bytes sent.
2569 """
2570 server, client = self._loopback()
2571 count = server.send(b('xy'))
2572 self.assertEquals(count, 2)
2573 self.assertEquals(client.recv(2), b('xy'))
2574
2575 try:
2576 memoryview
2577 except NameError:
2578 "cannot test sending memoryview without memoryview"
2579 else:
2580 def test_short_memoryview(self):
2581 """
2582 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002583 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002584 bytes sent.
2585 """
2586 server, client = self._loopback()
2587 count = server.send(memoryview(b('xy')))
2588 self.assertEquals(count, 2)
2589 self.assertEquals(client.recv(2), b('xy'))
2590
2591
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002592 try:
2593 buffer
2594 except NameError:
2595 "cannot test sending buffer without buffer"
2596 else:
2597 def test_short_buffer(self):
2598 """
2599 When passed a buffer containing a small number of bytes,
2600 :py:obj:`Connection.send` transmits all of them and returns the number of
2601 bytes sent.
2602 """
2603 server, client = self._loopback()
2604 count = server.send(buffer(b('xy')))
2605 self.assertEquals(count, 2)
2606 self.assertEquals(client.recv(2), b('xy'))
2607
2608
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002609
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002610def _make_memoryview(size):
2611 """
2612 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2613 size.
2614 """
2615 return memoryview(bytearray(size))
2616
2617
2618
Cory Benfield62d10332014-06-15 10:03:41 +01002619class ConnectionRecvIntoTests(TestCase, _LoopbackMixin):
2620 """
2621 Tests for :py:obj:`Connection.recv_into`
2622 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002623 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002624 """
2625 Assert that when the given buffer is passed to
2626 ``Connection.recv_into``, whatever bytes are available to be received
2627 that fit into that buffer are written into that buffer.
2628 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002629 output_buffer = factory(5)
2630
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002631 server, client = self._loopback()
2632 server.send(b('xy'))
2633
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002634 self.assertEqual(client.recv_into(output_buffer), 2)
2635 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002636
2637
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002638 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002639 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002640 :py:obj:`Connection.recv_into` can be passed a ``bytearray`` instance
2641 and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002642 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002643 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002644
2645
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002646 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002647 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002648 Assert that when the given buffer is passed to ``Connection.recv_into``
2649 along with a value for ``nbytes`` that is less than the size of that
2650 buffer, only ``nbytes`` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002651 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002652 output_buffer = factory(10)
2653
Cory Benfield62d10332014-06-15 10:03:41 +01002654 server, client = self._loopback()
2655 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002656
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002657 self.assertEqual(client.recv_into(output_buffer, 5), 5)
2658 self.assertEqual(
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002659 output_buffer, bytearray(b('abcde\x00\x00\x00\x00\x00'))
2660 )
2661
2662
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002663 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002664 """
2665 When called with a ``bytearray`` instance,
2666 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter and
2667 doesn't copy in more than that number of bytes.
2668 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002669 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002670
2671
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002672 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002673 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002674 Assert that if there are more bytes available to be read from the
2675 receive buffer than would fit into the buffer passed to
2676 :py:obj:`Connection.recv_into`, only as many as fit are written into
2677 it.
Cory Benfield62d10332014-06-15 10:03:41 +01002678 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002679 output_buffer = factory(5)
2680
Cory Benfield62d10332014-06-15 10:03:41 +01002681 server, client = self._loopback()
2682 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002683
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002684 self.assertEqual(client.recv_into(output_buffer), 5)
2685 self.assertEqual(output_buffer, bytearray(b('abcde')))
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002686 rest = client.recv(5)
2687 self.assertEqual(b('fghij'), rest)
2688
2689
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002690 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002691 """
2692 When called with a ``bytearray`` instance,
2693 :py:obj:`Connection.recv_into` respects the size of the array and
2694 doesn't write more bytes into it than will fit.
2695 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002696 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002697
2698
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002699 def _really_doesnt_overfill_test(self, factory):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002700 """
2701 Assert that if the value given by ``nbytes`` is greater than the actual
2702 size of the output buffer passed to :py:obj:`Connection.recv_into`, the
2703 behavior is as if no value was given for ``nbytes`` at all.
2704 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002705 output_buffer = factory(5)
2706
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002707 server, client = self._loopback()
2708 server.send(b('abcdefghij'))
2709
2710 self.assertEqual(client.recv_into(output_buffer, 50), 5)
2711 self.assertEqual(output_buffer, bytearray(b('abcde')))
2712 rest = client.recv(5)
2713 self.assertEqual(b('fghij'), rest)
2714
2715
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002716 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002717 """
2718 When called with a ``bytearray`` instance and an ``nbytes`` value that
2719 is too large, :py:obj:`Connection.recv_into` respects the size of the
2720 array and not the ``nbytes`` value and doesn't write more bytes into
2721 the buffer than will fit.
2722 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002723 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002724
2725
Cory Benfield62d10332014-06-15 10:03:41 +01002726 try:
2727 memoryview
2728 except NameError:
2729 "cannot test recv_into memoryview without memoryview"
2730 else:
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002731 def test_memoryview_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002732 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002733 :py:obj:`Connection.recv_into` can be passed a ``memoryview``
2734 instance and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002735 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002736 self._no_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002737
2738
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002739 def test_memoryview_respects_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002740 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002741 When called with a ``memoryview`` instance,
2742 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter
2743 and doesn't copy more than that number of bytes in.
Cory Benfield62d10332014-06-15 10:03:41 +01002744 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002745 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002746
2747
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002748 def test_memoryview_doesnt_overfill(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002749 """
Jean-Paul Calderone8fd82552015-03-15 17:21:07 -04002750 When called with a ``memoryview`` instance,
2751 :py:obj:`Connection.recv_into` respects the size of the array and
2752 doesn't write more bytes into it than will fit.
Cory Benfield62d10332014-06-15 10:03:41 +01002753 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002754 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002755
2756
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002757 def test_memoryview_really_doesnt_overfill(self):
2758 """
2759 When called with a ``memoryview`` instance and an ``nbytes`` value
2760 that is too large, :py:obj:`Connection.recv_into` respects the size
2761 of the array and not the ``nbytes`` value and doesn't write more
2762 bytes into the buffer than will fit.
2763 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002764 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002765
2766
Cory Benfield62d10332014-06-15 10:03:41 +01002767
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002768class ConnectionSendallTests(TestCase, _LoopbackMixin):
2769 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002770 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002771 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002772 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002773 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002774 When called with arguments other than a string argument for its first
2775 parameter or with more than two arguments, :py:obj:`Connection.sendall`
2776 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002777 """
2778 connection = Connection(Context(TLSv1_METHOD), None)
2779 self.assertRaises(TypeError, connection.sendall)
2780 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002781 self.assertRaises(
2782 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002783
2784
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002785 def test_short(self):
2786 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002787 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002788 it.
2789 """
2790 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04002791 server.sendall(b('x'))
2792 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002793
2794
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002795 try:
2796 memoryview
2797 except NameError:
2798 "cannot test sending memoryview without memoryview"
2799 else:
2800 def test_short_memoryview(self):
2801 """
2802 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002803 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002804 """
2805 server, client = self._loopback()
2806 server.sendall(memoryview(b('x')))
2807 self.assertEquals(client.recv(1), b('x'))
2808
2809
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002810 try:
2811 buffer
2812 except NameError:
2813 "cannot test sending buffers without buffers"
2814 else:
2815 def test_short_buffers(self):
2816 """
2817 When passed a buffer containing a small number of bytes,
2818 :py:obj:`Connection.sendall` transmits all of them.
2819 """
2820 server, client = self._loopback()
2821 server.sendall(buffer(b('x')))
2822 self.assertEquals(client.recv(1), b('x'))
2823
2824
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002825 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002826 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002827 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002828 it even if this requires multiple calls of an underlying write function.
2829 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002830 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04002831 # Should be enough, underlying SSL_write should only do 16k at a time.
2832 # On Windows, after 32k of bytes the write will block (forever - because
2833 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04002834 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002835 server.sendall(message)
2836 accum = []
2837 received = 0
2838 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04002839 data = client.recv(1024)
2840 accum.append(data)
2841 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04002842 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002843
2844
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002845 def test_closed(self):
2846 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002847 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002848 write error from the low level write call.
2849 """
2850 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04002851 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002852 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02002853 if platform == "win32":
2854 self.assertEqual(exc.args[0], ESHUTDOWN)
2855 else:
2856 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002857
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002858
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002859
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002860class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
2861 """
2862 Tests for SSL renegotiation APIs.
2863 """
2864 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002865 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002866 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002867 arguments.
2868 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002869 connection = Connection(Context(TLSv1_METHOD), None)
2870 self.assertRaises(TypeError, connection.renegotiate, None)
2871
2872
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002873 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002874 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002875 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002876 any arguments.
2877 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002878 connection = Connection(Context(TLSv1_METHOD), None)
2879 self.assertRaises(TypeError, connection.total_renegotiations, None)
2880
2881
2882 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002883 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002884 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002885 renegotiations have happened.
2886 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002887 connection = Connection(Context(TLSv1_METHOD), None)
2888 self.assertEquals(connection.total_renegotiations(), 0)
2889
2890
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002891# def test_renegotiate(self):
2892# """
2893# """
2894# server, client = self._loopback()
2895
2896# server.send("hello world")
2897# self.assertEquals(client.recv(len("hello world")), "hello world")
2898
2899# self.assertEquals(server.total_renegotiations(), 0)
2900# self.assertTrue(server.renegotiate())
2901
2902# server.setblocking(False)
2903# client.setblocking(False)
2904# while server.renegotiate_pending():
2905# client.do_handshake()
2906# server.do_handshake()
2907
2908# self.assertEquals(server.total_renegotiations(), 1)
2909
2910
2911
2912
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002913class ErrorTests(TestCase):
2914 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002915 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002916 """
2917 def test_type(self):
2918 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002919 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002920 """
2921 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05002922 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05002923
2924
2925
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002926class ConstantsTests(TestCase):
2927 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002928 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002929
2930 These are values defined by OpenSSL intended only to be used as flags to
2931 OpenSSL APIs. The only assertions it seems can be made about them is
2932 their values.
2933 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002934 # unittest.TestCase has no skip mechanism
2935 if OP_NO_QUERY_MTU is not None:
2936 def test_op_no_query_mtu(self):
2937 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002938 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002939 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002940 """
2941 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
2942 else:
2943 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002944
2945
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002946 if OP_COOKIE_EXCHANGE is not None:
2947 def test_op_cookie_exchange(self):
2948 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002949 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002950 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002951 """
2952 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
2953 else:
2954 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002955
2956
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002957 if OP_NO_TICKET is not None:
2958 def test_op_no_ticket(self):
2959 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002960 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002961 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002962 """
2963 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04002964 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002965 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05002966
2967
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002968 if OP_NO_COMPRESSION is not None:
2969 def test_op_no_compression(self):
2970 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002971 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
2972 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002973 """
2974 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
2975 else:
2976 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
2977
2978
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002979 def test_sess_cache_off(self):
2980 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002981 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
2982 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002983 """
2984 self.assertEqual(0x0, SESS_CACHE_OFF)
2985
2986
2987 def test_sess_cache_client(self):
2988 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002989 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
2990 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002991 """
2992 self.assertEqual(0x1, SESS_CACHE_CLIENT)
2993
2994
2995 def test_sess_cache_server(self):
2996 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002997 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
2998 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002999 """
3000 self.assertEqual(0x2, SESS_CACHE_SERVER)
3001
3002
3003 def test_sess_cache_both(self):
3004 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003005 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3006 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003007 """
3008 self.assertEqual(0x3, SESS_CACHE_BOTH)
3009
3010
3011 def test_sess_cache_no_auto_clear(self):
3012 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003013 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3014 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3015 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003016 """
3017 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
3018
3019
3020 def test_sess_cache_no_internal_lookup(self):
3021 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003022 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3023 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3024 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003025 """
3026 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
3027
3028
3029 def test_sess_cache_no_internal_store(self):
3030 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003031 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3032 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3033 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003034 """
3035 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
3036
3037
3038 def test_sess_cache_no_internal(self):
3039 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003040 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3041 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
3042 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003043 """
3044 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
3045
3046
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04003047
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003048class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05003049 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003050 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003051 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003052 def _server(self, sock):
3053 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003054 Create a new server-side SSL :py:obj:`Connection` object wrapped around
3055 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003056 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003057 # Create the server side Connection. This is mostly setup boilerplate
3058 # - use TLSv1, use a particular certificate, etc.
3059 server_ctx = Context(TLSv1_METHOD)
3060 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
3061 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
3062 server_store = server_ctx.get_cert_store()
3063 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3064 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3065 server_ctx.check_privatekey()
3066 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003067 # Here the Connection is actually created. If None is passed as the 2nd
3068 # parameter, it indicates a memory BIO should be created.
3069 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003070 server_conn.set_accept_state()
3071 return server_conn
3072
3073
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003074 def _client(self, sock):
3075 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003076 Create a new client-side SSL :py:obj:`Connection` object wrapped around
3077 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003078 """
3079 # Now create the client side Connection. Similar boilerplate to the
3080 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003081 client_ctx = Context(TLSv1_METHOD)
3082 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
3083 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
3084 client_store = client_ctx.get_cert_store()
3085 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
3086 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
3087 client_ctx.check_privatekey()
3088 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003089 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003090 client_conn.set_connect_state()
3091 return client_conn
3092
3093
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003094 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003095 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003096 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003097 reading from the output of each and writing those bytes to the input of
3098 the other and in this way establish a connection and exchange
3099 application-level bytes with each other.
3100 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003101 server_conn = self._server(None)
3102 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003103
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003104 # There should be no key or nonces yet.
3105 self.assertIdentical(server_conn.master_key(), None)
3106 self.assertIdentical(server_conn.client_random(), None)
3107 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003108
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003109 # First, the handshake needs to happen. We'll deliver bytes back and
3110 # forth between the client and server until neither of them feels like
3111 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003112 self.assertIdentical(
3113 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003114
3115 # Now that the handshake is done, there should be a key and nonces.
3116 self.assertNotIdentical(server_conn.master_key(), None)
3117 self.assertNotIdentical(server_conn.client_random(), None)
3118 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04003119 self.assertEquals(server_conn.client_random(), client_conn.client_random())
3120 self.assertEquals(server_conn.server_random(), client_conn.server_random())
3121 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
3122 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003123
3124 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003125 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05003126
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003127 server_conn.write(important_message)
3128 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003129 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003130 (client_conn, important_message))
3131
3132 client_conn.write(important_message[::-1])
3133 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003134 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003135 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003136
3137
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003138 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003139 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003140 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003141
3142 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09003143 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003144 this test fails, there must be a problem outside the memory BIO
3145 code, as no memory BIO is involved here). Even though this isn't a
3146 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003147 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04003148 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003149
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003150 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05003151 client_conn.send(important_message)
3152 msg = server_conn.recv(1024)
3153 self.assertEqual(msg, important_message)
3154
3155 # Again in the other direction, just for fun.
3156 important_message = important_message[::-1]
3157 server_conn.send(important_message)
3158 msg = client_conn.recv(1024)
3159 self.assertEqual(msg, important_message)
3160
3161
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04003162 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003163 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003164 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
3165 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003166 """
3167 context = Context(SSLv3_METHOD)
3168 client = socket()
3169 clientSSL = Connection(context, client)
3170 self.assertRaises( TypeError, clientSSL.bio_read, 100)
3171 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04003172 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003173
3174
3175 def test_outgoingOverflow(self):
3176 """
3177 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09003178 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003179 returned and that many bytes from the beginning of the input can be
3180 read from the other end of the connection.
3181 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003182 server = self._server(None)
3183 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003184
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003185 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003186
3187 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003188 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003189 # Sanity check. We're trying to test what happens when the entire
3190 # input can't be sent. If the entire input was sent, this test is
3191 # meaningless.
3192 self.assertTrue(sent < size)
3193
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003194 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003195 self.assertIdentical(receiver, server)
3196
3197 # We can rely on all of these bytes being received at once because
3198 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
3199 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003200
3201
3202 def test_shutdown(self):
3203 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003204 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
3205 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003206 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003207 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003208 server.bio_shutdown()
3209 e = self.assertRaises(Error, server.recv, 1024)
3210 # We don't want WantReadError or ZeroReturnError or anything - it's a
3211 # handshake failure.
3212 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003213
3214
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003215 def test_unexpectedEndOfFile(self):
3216 """
3217 If the connection is lost before an orderly SSL shutdown occurs,
3218 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
3219 "Unexpected EOF".
3220 """
3221 server_conn, client_conn = self._loopback()
3222 client_conn.sock_shutdown(SHUT_RDWR)
3223 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
3224 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
3225
3226
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003227 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003228 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003229 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 -04003230
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003231 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003232 before the client and server are connected to each other. This
3233 function should specify a list of CAs for the server to send to the
3234 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09003235 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003236 times.
3237 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003238 server = self._server(None)
3239 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003240 self.assertEqual(client.get_client_ca_list(), [])
3241 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003242 ctx = server.get_context()
3243 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003244 self.assertEqual(client.get_client_ca_list(), [])
3245 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003246 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003247 self.assertEqual(client.get_client_ca_list(), expected)
3248 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003249
3250
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003251 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003252 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003253 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003254 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003255 """
3256 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003257 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
3258 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
3259 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003260
3261
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003262 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003263 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003264 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003265 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09003266 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003267 after the connection is set up.
3268 """
3269 def no_ca(ctx):
3270 ctx.set_client_ca_list([])
3271 return []
3272 self._check_client_ca_list(no_ca)
3273
3274
3275 def test_set_one_ca_list(self):
3276 """
3277 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003278 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003279 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003280 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003281 X509Name after the connection is set up.
3282 """
3283 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3284 cadesc = cacert.get_subject()
3285 def single_ca(ctx):
3286 ctx.set_client_ca_list([cadesc])
3287 return [cadesc]
3288 self._check_client_ca_list(single_ca)
3289
3290
3291 def test_set_multiple_ca_list(self):
3292 """
3293 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003294 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003295 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003296 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003297 X509Names after the connection is set up.
3298 """
3299 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3300 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3301
3302 sedesc = secert.get_subject()
3303 cldesc = clcert.get_subject()
3304
3305 def multiple_ca(ctx):
3306 L = [sedesc, cldesc]
3307 ctx.set_client_ca_list(L)
3308 return L
3309 self._check_client_ca_list(multiple_ca)
3310
3311
3312 def test_reset_ca_list(self):
3313 """
3314 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09003315 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003316 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003317 """
3318 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3319 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3320 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3321
3322 cadesc = cacert.get_subject()
3323 sedesc = secert.get_subject()
3324 cldesc = clcert.get_subject()
3325
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003326 def changed_ca(ctx):
3327 ctx.set_client_ca_list([sedesc, cldesc])
3328 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003329 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003330 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003331
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003332
3333 def test_mutated_ca_list(self):
3334 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003335 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003336 afterwards, this does not affect the list of CA names sent to the
3337 client.
3338 """
3339 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3340 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3341
3342 cadesc = cacert.get_subject()
3343 sedesc = secert.get_subject()
3344
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003345 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003346 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003347 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003348 L.append(sedesc)
3349 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003350 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003351
3352
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003353 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003354 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003355 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003356 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003357 """
3358 ctx = Context(TLSv1_METHOD)
3359 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003360 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003361 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003362 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003363
3364
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003365 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003366 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003367 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09003368 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003369 """
3370 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3371 cadesc = cacert.get_subject()
3372 def single_ca(ctx):
3373 ctx.add_client_ca(cacert)
3374 return [cadesc]
3375 self._check_client_ca_list(single_ca)
3376
3377
3378 def test_multiple_add_client_ca(self):
3379 """
3380 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09003381 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003382 """
3383 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3384 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3385
3386 cadesc = cacert.get_subject()
3387 sedesc = secert.get_subject()
3388
3389 def multiple_ca(ctx):
3390 ctx.add_client_ca(cacert)
3391 ctx.add_client_ca(secert)
3392 return [cadesc, sedesc]
3393 self._check_client_ca_list(multiple_ca)
3394
3395
3396 def test_set_and_add_client_ca(self):
3397 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003398 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
3399 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003400 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003401 """
3402 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3403 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3404 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3405
3406 cadesc = cacert.get_subject()
3407 sedesc = secert.get_subject()
3408 cldesc = clcert.get_subject()
3409
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003410 def mixed_set_add_ca(ctx):
3411 ctx.set_client_ca_list([cadesc, sedesc])
3412 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003413 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003414 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003415
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003416
3417 def test_set_after_add_client_ca(self):
3418 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003419 A call to :py:obj:`Context.set_client_ca_list` after a call to
3420 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003421 call with the names specified by the latter cal.
3422 """
3423 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3424 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3425 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3426
3427 cadesc = cacert.get_subject()
3428 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003429
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003430 def set_replaces_add_ca(ctx):
3431 ctx.add_client_ca(clcert)
3432 ctx.set_client_ca_list([cadesc])
3433 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003434 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003435 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003436
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003437
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003438
3439class ConnectionBIOTests(TestCase):
3440 """
3441 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3442 """
3443 def test_wantReadError(self):
3444 """
3445 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
3446 if there are no bytes available to be read from the BIO.
3447 """
3448 ctx = Context(TLSv1_METHOD)
3449 conn = Connection(ctx, None)
3450 self.assertRaises(WantReadError, conn.bio_read, 1024)
3451
3452
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003453 def test_buffer_size(self):
3454 """
3455 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3456 number of bytes to read and return.
3457 """
3458 ctx = Context(TLSv1_METHOD)
3459 conn = Connection(ctx, None)
3460 conn.set_connect_state()
3461 try:
3462 conn.do_handshake()
3463 except WantReadError:
3464 pass
3465 data = conn.bio_read(2)
3466 self.assertEqual(2, len(data))
3467
3468
3469 if not PY3:
3470 def test_buffer_size_long(self):
3471 """
3472 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3473 :py:obj:`long` as well as :py:obj:`int`.
3474 """
3475 ctx = Context(TLSv1_METHOD)
3476 conn = Connection(ctx, None)
3477 conn.set_connect_state()
3478 try:
3479 conn.do_handshake()
3480 except WantReadError:
3481 pass
3482 data = conn.bio_read(long(2))
3483 self.assertEqual(2, len(data))
3484
3485
3486
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003487
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003488class InfoConstantTests(TestCase):
3489 """
3490 Tests for assorted constants exposed for use in info callbacks.
3491 """
3492 def test_integers(self):
3493 """
3494 All of the info constants are integers.
3495
3496 This is a very weak test. It would be nice to have one that actually
3497 verifies that as certain info events happen, the value passed to the
3498 info callback matches up with the constant exposed by OpenSSL.SSL.
3499 """
3500 for const in [
3501 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3502 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3503 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3504 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3505 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
3506 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
3507
3508 self.assertTrue(isinstance(const, int))
3509
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003510
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003511if __name__ == '__main__':
3512 main()