blob: bd0014242db1fffeba0d11df8e7f175348f758c6 [file] [log] [blame]
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05001# Copyright (C) Jean-Paul Calderone
2# See LICENSE for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04003
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04004"""
Jonathan Ballet648875f2011-07-16 14:14:58 +09005Unit tests for :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04006"""
7
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05008from gc import collect, get_referrers
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02009from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE, ESHUTDOWN
Jean-Paul Calderone516c12c2015-04-13 20:34:57 -040010from sys import platform, getfilesystemencoding
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070011from socket import SHUT_RDWR, error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040012from os import makedirs
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040013from os.path import join
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -040014from unittest import main
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040015from weakref import ref
Abraham Martinef063482015-03-25 14:06:24 +000016from warnings import catch_warnings, simplefilter
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050017
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -040018from six import PY3, text_type, u
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050019
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040020from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080021from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040022from OpenSSL.crypto import dump_privatekey, load_privatekey
23from OpenSSL.crypto import dump_certificate, load_certificate
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040024from OpenSSL.crypto import get_elliptic_curves
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040025
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040026from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
27from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040028from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040029from OpenSSL.SSL import (
30 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
31 TLSv1_1_METHOD, TLSv1_2_METHOD)
32from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040033from OpenSSL.SSL import (
34 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040035
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040036from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050037 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
38 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
39 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
40
41from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070042 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050043from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070044 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040045
Jean-Paul Calderone17eca482015-04-13 20:31:07 -040046from OpenSSL.test.util import WARNING_TYPE_EXPECTED, NON_ASCII, TestCase, b
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040047from OpenSSL.test.test_crypto import (
48 cleartextCertificatePEM, cleartextPrivateKeyPEM)
49from OpenSSL.test.test_crypto import (
50 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
51 root_cert_pem)
52
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050053try:
54 from OpenSSL.SSL import OP_NO_QUERY_MTU
55except ImportError:
56 OP_NO_QUERY_MTU = None
57try:
58 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
59except ImportError:
60 OP_COOKIE_EXCHANGE = None
61try:
62 from OpenSSL.SSL import OP_NO_TICKET
63except ImportError:
64 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040065
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040066try:
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -040067 from OpenSSL.SSL import OP_NO_COMPRESSION
68except ImportError:
69 OP_NO_COMPRESSION = None
70
71try:
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040072 from OpenSSL.SSL import MODE_RELEASE_BUFFERS
73except ImportError:
74 MODE_RELEASE_BUFFERS = None
75
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040076try:
77 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
78except ImportError:
79 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
80
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040081from OpenSSL.SSL import (
82 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
83 SSL_ST_OK, SSL_ST_RENEGOTIATE,
84 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
85 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
86 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
87 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040088
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040089# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
90# to use)
91dhparam = """\
92-----BEGIN DH PARAMETERS-----
93MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
94-----END DH PARAMETERS-----
95"""
96
97
Jean-Paul Calderone05826732015-04-12 11:38:49 -040098def join_bytes_or_unicode(prefix, suffix):
99 """
100 Join two path components of either ``bytes`` or ``unicode``.
101
102 The return type is the same as the type of ``prefix``.
103 """
104 # If the types are the same, nothing special is necessary.
105 if type(prefix) == type(suffix):
106 return join(prefix, suffix)
107
108 # Otherwise, coerce suffix to the type of prefix.
109 if isinstance(prefix, text_type):
110 return join(prefix, suffix.decode(getfilesystemencoding()))
111 else:
112 return join(prefix, suffix.encode(getfilesystemencoding()))
113
114
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400115def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400116 return ok
117
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400118
Rick Deanb1ccd562009-07-09 23:52:39 -0500119def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400120 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400121 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400122 """
123 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500124 port = socket()
125 port.bind(('', 0))
126 port.listen(1)
127 client = socket()
128 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400129 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400130 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500131 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500132
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400133 # Let's pass some unencrypted data to make sure our socket connection is
134 # fine. Just one byte, so we don't have to worry about buffers getting
135 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400136 server.send(b("x"))
137 assert client.recv(1024) == b("x")
138 client.send(b("y"))
139 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500140
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400141 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400142 server.setblocking(False)
143 client.setblocking(False)
144
Rick Deanb1ccd562009-07-09 23:52:39 -0500145 return (server, client)
146
147
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400148
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400149def handshake(client, server):
150 conns = [client, server]
151 while conns:
152 for conn in conns:
153 try:
154 conn.do_handshake()
155 except WantReadError:
156 pass
157 else:
158 conns.remove(conn)
159
160
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400161def _create_certificate_chain():
162 """
163 Construct and return a chain of certificates.
164
165 1. A new self-signed certificate authority certificate (cacert)
166 2. A new intermediate certificate signed by cacert (icert)
167 3. A new server certificate signed by icert (scert)
168 """
169 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
170
171 # Step 1
172 cakey = PKey()
173 cakey.generate_key(TYPE_RSA, 512)
174 cacert = X509()
175 cacert.get_subject().commonName = "Authority Certificate"
176 cacert.set_issuer(cacert.get_subject())
177 cacert.set_pubkey(cakey)
178 cacert.set_notBefore(b("20000101000000Z"))
179 cacert.set_notAfter(b("20200101000000Z"))
180 cacert.add_extensions([caext])
181 cacert.set_serial_number(0)
182 cacert.sign(cakey, "sha1")
183
184 # Step 2
185 ikey = PKey()
186 ikey.generate_key(TYPE_RSA, 512)
187 icert = X509()
188 icert.get_subject().commonName = "Intermediate Certificate"
189 icert.set_issuer(cacert.get_subject())
190 icert.set_pubkey(ikey)
191 icert.set_notBefore(b("20000101000000Z"))
192 icert.set_notAfter(b("20200101000000Z"))
193 icert.add_extensions([caext])
194 icert.set_serial_number(0)
195 icert.sign(cakey, "sha1")
196
197 # Step 3
198 skey = PKey()
199 skey.generate_key(TYPE_RSA, 512)
200 scert = X509()
201 scert.get_subject().commonName = "Server Certificate"
202 scert.set_issuer(icert.get_subject())
203 scert.set_pubkey(skey)
204 scert.set_notBefore(b("20000101000000Z"))
205 scert.set_notAfter(b("20200101000000Z"))
206 scert.add_extensions([
207 X509Extension(b('basicConstraints'), True, b('CA:false'))])
208 scert.set_serial_number(0)
209 scert.sign(ikey, "sha1")
210
211 return [(cakey, cacert), (ikey, icert), (skey, scert)]
212
213
214
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400215class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400216 """
217 Helper mixin which defines methods for creating a connected socket pair and
218 for forcing two connected SSL sockets to talk to each other via memory BIOs.
219 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500220 def _loopbackClientFactory(self, socket):
221 client = Connection(Context(TLSv1_METHOD), socket)
222 client.set_connect_state()
223 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400224
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500225
226 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400227 ctx = Context(TLSv1_METHOD)
228 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
229 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500230 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400231 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500232 return server
233
234
235 def _loopback(self, serverFactory=None, clientFactory=None):
236 if serverFactory is None:
237 serverFactory = self._loopbackServerFactory
238 if clientFactory is None:
239 clientFactory = self._loopbackClientFactory
240
241 (server, client) = socket_pair()
242 server = serverFactory(server)
243 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400244
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400245 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400246
247 server.setblocking(True)
248 client.setblocking(True)
249 return server, client
250
251
252 def _interactInMemory(self, client_conn, server_conn):
253 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900254 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400255 objects. Copy bytes back and forth between their send/receive buffers
256 for as long as there is anything to copy. When there is nothing more
Jonathan Ballet648875f2011-07-16 14:14:58 +0900257 to copy, return :py:obj:`None`. If one of them actually manages to deliver
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400258 some application bytes, return a two-tuple of the connection from which
259 the bytes were read and the bytes themselves.
260 """
261 wrote = True
262 while wrote:
263 # Loop until neither side has anything to say
264 wrote = False
265
266 # Copy stuff from each side's send buffer to the other side's
267 # receive buffer.
268 for (read, write) in [(client_conn, server_conn),
269 (server_conn, client_conn)]:
270
271 # Give the side a chance to generate some more bytes, or
272 # succeed.
273 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400274 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400275 except WantReadError:
276 # It didn't succeed, so we'll hope it generated some
277 # output.
278 pass
279 else:
280 # It did succeed, so we'll stop now and let the caller deal
281 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400282 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400283
284 while True:
285 # Keep copying as long as there's more stuff there.
286 try:
287 dirty = read.bio_read(4096)
288 except WantReadError:
289 # Okay, nothing more waiting to be sent. Stop
290 # processing this send buffer.
291 break
292 else:
293 # Keep track of the fact that someone generated some
294 # output.
295 wrote = True
296 write.bio_write(dirty)
297
298
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400299 def _handshakeInMemory(self, client_conn, server_conn):
Jean-Paul Calderoneb2b40782014-05-06 08:47:40 -0400300 """
301 Perform the TLS handshake between two :py:class:`Connection` instances
302 connected to each other via memory BIOs.
303 """
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400304 client_conn.set_connect_state()
305 server_conn.set_accept_state()
306
307 for conn in [client_conn, server_conn]:
308 try:
309 conn.do_handshake()
310 except WantReadError:
311 pass
312
313 self._interactInMemory(client_conn, server_conn)
314
315
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400316
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400317class VersionTests(TestCase):
318 """
319 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900320 :py:obj:`OpenSSL.SSL.SSLeay_version` and
321 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400322 """
323 def test_OPENSSL_VERSION_NUMBER(self):
324 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900325 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400326 byte and the patch, fix, minor, and major versions in the
327 nibbles above that.
328 """
329 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
330
331
332 def test_SSLeay_version(self):
333 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900334 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400335 one of a number of version strings based on that indicator.
336 """
337 versions = {}
338 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
339 SSLEAY_PLATFORM, SSLEAY_DIR]:
340 version = SSLeay_version(t)
341 versions[version] = t
342 self.assertTrue(isinstance(version, bytes))
343 self.assertEqual(len(versions), 5)
344
345
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400346
347class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400348 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900349 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400350 """
351 def test_method(self):
352 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900353 :py:obj:`Context` can be instantiated with one of :py:obj:`SSLv2_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400354 :py:obj:`SSLv3_METHOD`, :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
355 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400356 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400357 methods = [
358 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
359 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400360 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400361
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400362
363 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
364 for meth in maybe:
365 try:
366 Context(meth)
367 except (Error, ValueError):
368 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
369 # don't. Difficult to say in advance.
370 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400371
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400372 self.assertRaises(TypeError, Context, "")
373 self.assertRaises(ValueError, Context, 10)
374
375
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500376 if not PY3:
377 def test_method_long(self):
378 """
379 On Python 2 :py:class:`Context` accepts values of type
380 :py:obj:`long` as well as :py:obj:`int`.
381 """
382 Context(long(TLSv1_METHOD))
383
384
385
Rick Deane15b1472009-07-09 15:53:42 -0500386 def test_type(self):
387 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900388 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400389 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500390 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400391 self.assertIdentical(Context, ContextType)
392 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500393
394
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400395 def test_use_privatekey(self):
396 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900397 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400398 """
399 key = PKey()
400 key.generate_key(TYPE_RSA, 128)
401 ctx = Context(TLSv1_METHOD)
402 ctx.use_privatekey(key)
403 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400404
405
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800406 def test_use_privatekey_file_missing(self):
407 """
408 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error`
409 when passed the name of a file which does not exist.
410 """
411 ctx = Context(TLSv1_METHOD)
412 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
413
414
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400415 def _use_privatekey_file_test(self, pemfile, filetype):
416 """
417 Verify that calling ``Context.use_privatekey_file`` with the given
418 arguments does not raise an exception.
419 """
420 key = PKey()
421 key.generate_key(TYPE_RSA, 128)
422
423 with open(pemfile, "wt") as pem:
424 pem.write(
425 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
426 )
427
428 ctx = Context(TLSv1_METHOD)
429 ctx.use_privatekey_file(pemfile, filetype)
430
431
432 def test_use_privatekey_file_bytes(self):
433 """
434 A private key can be specified from a file by passing a ``bytes``
435 instance giving the file name to ``Context.use_privatekey_file``.
436 """
437 self._use_privatekey_file_test(
438 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
439 FILETYPE_PEM,
440 )
441
442
443 def test_use_privatekey_file_unicode(self):
444 """
445 A private key can be specified from a file by passing a ``unicode``
446 instance giving the file name to ``Context.use_privatekey_file``.
447 """
448 self._use_privatekey_file_test(
449 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
450 FILETYPE_PEM,
451 )
452
453
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500454 if not PY3:
455 def test_use_privatekey_file_long(self):
456 """
457 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
458 filetype of type :py:obj:`long` as well as :py:obj:`int`.
459 """
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400460 self._use_privatekey_file_test(self.mktemp(), long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500461
462
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800463 def test_use_certificate_wrong_args(self):
464 """
465 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
466 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as an
467 argument.
468 """
469 ctx = Context(TLSv1_METHOD)
470 self.assertRaises(TypeError, ctx.use_certificate)
471 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
472 self.assertRaises(TypeError, ctx.use_certificate, X509(), "hello, world")
473
474
475 def test_use_certificate_uninitialized(self):
476 """
477 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
478 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
479 initialized (ie, which does not actually have any certificate data).
480 """
481 ctx = Context(TLSv1_METHOD)
482 self.assertRaises(Error, ctx.use_certificate, X509())
483
484
485 def test_use_certificate(self):
486 """
487 :py:obj:`Context.use_certificate` sets the certificate which will be
488 used to identify connections created using the context.
489 """
490 # TODO
491 # Hard to assert anything. But we could set a privatekey then ask
492 # OpenSSL if the cert and key agree using check_privatekey. Then as
493 # long as check_privatekey works right we're good...
494 ctx = Context(TLSv1_METHOD)
495 ctx.use_certificate(load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
496
497
498 def test_use_certificate_file_wrong_args(self):
499 """
500 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
501 called with zero arguments or more than two arguments, or if the first
502 argument is not a byte string or the second argumnent is not an integer.
503 """
504 ctx = Context(TLSv1_METHOD)
505 self.assertRaises(TypeError, ctx.use_certificate_file)
506 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile", object())
507 self.assertRaises(
508 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM, object())
509 self.assertRaises(
510 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
511 self.assertRaises(
512 TypeError, ctx.use_certificate_file, b"somefile", object())
513
514
515 def test_use_certificate_file_missing(self):
516 """
517 :py:obj:`Context.use_certificate_file` raises
518 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does not
519 exist.
520 """
521 ctx = Context(TLSv1_METHOD)
522 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
523
524
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400525 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800526 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400527 Verify that calling ``Context.use_certificate_file`` with the given
528 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800529 """
530 # TODO
531 # Hard to assert anything. But we could set a privatekey then ask
532 # OpenSSL if the cert and key agree using check_privatekey. Then as
533 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400534 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800535 pem_file.write(cleartextCertificatePEM)
536
537 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400538 ctx.use_certificate_file(certificate_file)
539
540
541 def test_use_certificate_file_bytes(self):
542 """
543 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
544 ``bytes`` filename) which will be used to identify connections created
545 using the context.
546 """
547 filename = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
548 self._use_certificate_file_test(filename)
549
550
551 def test_use_certificate_file_unicode(self):
552 """
553 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
554 ``bytes`` filename) which will be used to identify connections created
555 using the context.
556 """
557 filename = self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
558 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800559
560
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500561 if not PY3:
562 def test_use_certificate_file_long(self):
563 """
564 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
565 filetype of type :py:obj:`long` as well as :py:obj:`int`.
566 """
567 pem_filename = self.mktemp()
568 with open(pem_filename, "wb") as pem_file:
569 pem_file.write(cleartextCertificatePEM)
570
571 ctx = Context(TLSv1_METHOD)
572 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
573
574
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500575 def test_check_privatekey_valid(self):
576 """
577 :py:obj:`Context.check_privatekey` returns :py:obj:`None` if the
578 :py:obj:`Context` instance has been configured to use a matched key and
579 certificate pair.
580 """
581 key = load_privatekey(FILETYPE_PEM, client_key_pem)
582 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
583 context = Context(TLSv1_METHOD)
584 context.use_privatekey(key)
585 context.use_certificate(cert)
586 self.assertIs(None, context.check_privatekey())
587
588
589 def test_check_privatekey_invalid(self):
590 """
591 :py:obj:`Context.check_privatekey` raises :py:obj:`Error` if the
592 :py:obj:`Context` instance has been configured to use a key and
593 certificate pair which don't relate to each other.
594 """
595 key = load_privatekey(FILETYPE_PEM, client_key_pem)
596 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
597 context = Context(TLSv1_METHOD)
598 context.use_privatekey(key)
599 context.use_certificate(cert)
600 self.assertRaises(Error, context.check_privatekey)
601
602
603 def test_check_privatekey_wrong_args(self):
604 """
605 :py:obj:`Context.check_privatekey` raises :py:obj:`TypeError` if called
606 with other than no arguments.
607 """
608 context = Context(TLSv1_METHOD)
609 self.assertRaises(TypeError, context.check_privatekey, object())
610
611
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400612 def test_set_app_data_wrong_args(self):
613 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900614 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called with other than
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400615 one argument.
616 """
617 context = Context(TLSv1_METHOD)
618 self.assertRaises(TypeError, context.set_app_data)
619 self.assertRaises(TypeError, context.set_app_data, None, None)
620
621
622 def test_get_app_data_wrong_args(self):
623 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900624 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400625 arguments.
626 """
627 context = Context(TLSv1_METHOD)
628 self.assertRaises(TypeError, context.get_app_data, None)
629
630
631 def test_app_data(self):
632 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900633 :py:obj:`Context.set_app_data` stores an object for later retrieval using
634 :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400635 """
636 app_data = object()
637 context = Context(TLSv1_METHOD)
638 context.set_app_data(app_data)
639 self.assertIdentical(context.get_app_data(), app_data)
640
641
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400642 def test_set_options_wrong_args(self):
643 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900644 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with the wrong
645 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400646 """
647 context = Context(TLSv1_METHOD)
648 self.assertRaises(TypeError, context.set_options)
649 self.assertRaises(TypeError, context.set_options, None)
650 self.assertRaises(TypeError, context.set_options, 1, None)
651
652
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500653 def test_set_options(self):
654 """
655 :py:obj:`Context.set_options` returns the new options value.
656 """
657 context = Context(TLSv1_METHOD)
658 options = context.set_options(OP_NO_SSLv2)
659 self.assertTrue(OP_NO_SSLv2 & options)
660
661
662 if not PY3:
663 def test_set_options_long(self):
664 """
665 On Python 2 :py:obj:`Context.set_options` accepts values of type
666 :py:obj:`long` as well as :py:obj:`int`.
667 """
668 context = Context(TLSv1_METHOD)
669 options = context.set_options(long(OP_NO_SSLv2))
670 self.assertTrue(OP_NO_SSLv2 & options)
671
672
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300673 def test_set_mode_wrong_args(self):
674 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400675 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with the wrong
676 number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300677 """
678 context = Context(TLSv1_METHOD)
679 self.assertRaises(TypeError, context.set_mode)
680 self.assertRaises(TypeError, context.set_mode, None)
681 self.assertRaises(TypeError, context.set_mode, 1, None)
682
683
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400684 if MODE_RELEASE_BUFFERS is not None:
685 def test_set_mode(self):
686 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400687 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the newly
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400688 set mode.
689 """
690 context = Context(TLSv1_METHOD)
691 self.assertTrue(
692 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500693
694 if not PY3:
695 def test_set_mode_long(self):
696 """
697 On Python 2 :py:obj:`Context.set_mode` accepts values of type
698 :py:obj:`long` as well as :py:obj:`int`.
699 """
700 context = Context(TLSv1_METHOD)
701 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
702 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400703 else:
704 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
705
706
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400707 def test_set_timeout_wrong_args(self):
708 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900709 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with the wrong
710 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400711 """
712 context = Context(TLSv1_METHOD)
713 self.assertRaises(TypeError, context.set_timeout)
714 self.assertRaises(TypeError, context.set_timeout, None)
715 self.assertRaises(TypeError, context.set_timeout, 1, None)
716
717
718 def test_get_timeout_wrong_args(self):
719 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900720 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400721 """
722 context = Context(TLSv1_METHOD)
723 self.assertRaises(TypeError, context.get_timeout, None)
724
725
726 def test_timeout(self):
727 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900728 :py:obj:`Context.set_timeout` sets the session timeout for all connections
729 created using the context object. :py:obj:`Context.get_timeout` retrieves this
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400730 value.
731 """
732 context = Context(TLSv1_METHOD)
733 context.set_timeout(1234)
734 self.assertEquals(context.get_timeout(), 1234)
735
736
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500737 if not PY3:
738 def test_timeout_long(self):
739 """
740 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
741 `long` as well as int.
742 """
743 context = Context(TLSv1_METHOD)
744 context.set_timeout(long(1234))
745 self.assertEquals(context.get_timeout(), 1234)
746
747
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400748 def test_set_verify_depth_wrong_args(self):
749 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900750 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called with the wrong
751 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400752 """
753 context = Context(TLSv1_METHOD)
754 self.assertRaises(TypeError, context.set_verify_depth)
755 self.assertRaises(TypeError, context.set_verify_depth, None)
756 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
757
758
759 def test_get_verify_depth_wrong_args(self):
760 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900761 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400762 """
763 context = Context(TLSv1_METHOD)
764 self.assertRaises(TypeError, context.get_verify_depth, None)
765
766
767 def test_verify_depth(self):
768 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900769 :py:obj:`Context.set_verify_depth` sets the number of certificates in a chain
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400770 to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900771 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400772 """
773 context = Context(TLSv1_METHOD)
774 context.set_verify_depth(11)
775 self.assertEquals(context.get_verify_depth(), 11)
776
777
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500778 if not PY3:
779 def test_verify_depth_long(self):
780 """
781 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
782 type `long` as well as int.
783 """
784 context = Context(TLSv1_METHOD)
785 context.set_verify_depth(long(11))
786 self.assertEquals(context.get_verify_depth(), 11)
787
788
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400789 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400790 """
791 Write a new private key out to a new file, encrypted using the given
792 passphrase. Return the path to the new file.
793 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400794 key = PKey()
795 key.generate_key(TYPE_RSA, 128)
796 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400797 fObj = open(pemFile, 'w')
798 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
799 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400800 fObj.close()
801 return pemFile
802
803
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400804 def test_set_passwd_cb_wrong_args(self):
805 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900806 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called with the
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400807 wrong arguments or with a non-callable first argument.
808 """
809 context = Context(TLSv1_METHOD)
810 self.assertRaises(TypeError, context.set_passwd_cb)
811 self.assertRaises(TypeError, context.set_passwd_cb, None)
812 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
813
814
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400815 def test_set_passwd_cb(self):
816 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900817 :py:obj:`Context.set_passwd_cb` accepts a callable which will be invoked when
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400818 a private key is loaded from an encrypted PEM.
819 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400820 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400821 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400822 calledWith = []
823 def passphraseCallback(maxlen, verify, extra):
824 calledWith.append((maxlen, verify, extra))
825 return passphrase
826 context = Context(TLSv1_METHOD)
827 context.set_passwd_cb(passphraseCallback)
828 context.use_privatekey_file(pemFile)
829 self.assertTrue(len(calledWith), 1)
830 self.assertTrue(isinstance(calledWith[0][0], int))
831 self.assertTrue(isinstance(calledWith[0][1], int))
832 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400833
834
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400835 def test_passwd_callback_exception(self):
836 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900837 :py:obj:`Context.use_privatekey_file` propagates any exception raised by the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400838 passphrase callback.
839 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400840 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400841 def passphraseCallback(maxlen, verify, extra):
842 raise RuntimeError("Sorry, I am a fail.")
843
844 context = Context(TLSv1_METHOD)
845 context.set_passwd_cb(passphraseCallback)
846 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
847
848
849 def test_passwd_callback_false(self):
850 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900851 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400852 passphrase callback returns a false value.
853 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400854 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400855 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500856 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400857
858 context = Context(TLSv1_METHOD)
859 context.set_passwd_cb(passphraseCallback)
860 self.assertRaises(Error, context.use_privatekey_file, pemFile)
861
862
863 def test_passwd_callback_non_string(self):
864 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900865 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400866 passphrase callback returns a true non-string value.
867 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400868 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400869 def passphraseCallback(maxlen, verify, extra):
870 return 10
871
872 context = Context(TLSv1_METHOD)
873 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800874 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400875
876
877 def test_passwd_callback_too_long(self):
878 """
879 If the passphrase returned by the passphrase callback returns a string
880 longer than the indicated maximum length, it is truncated.
881 """
882 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400883 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400884 pemFile = self._write_encrypted_pem(passphrase)
885 def passphraseCallback(maxlen, verify, extra):
886 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400887 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400888
889 context = Context(TLSv1_METHOD)
890 context.set_passwd_cb(passphraseCallback)
891 # This shall succeed because the truncated result is the correct
892 # passphrase.
893 context.use_privatekey_file(pemFile)
894
895
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400896 def test_set_info_callback(self):
897 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900898 :py:obj:`Context.set_info_callback` accepts a callable which will be invoked
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400899 when certain information about an SSL connection is available.
900 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500901 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400902
903 clientSSL = Connection(Context(TLSv1_METHOD), client)
904 clientSSL.set_connect_state()
905
906 called = []
907 def info(conn, where, ret):
908 called.append((conn, where, ret))
909 context = Context(TLSv1_METHOD)
910 context.set_info_callback(info)
911 context.use_certificate(
912 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
913 context.use_privatekey(
914 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
915
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400916 serverSSL = Connection(context, server)
917 serverSSL.set_accept_state()
918
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500919 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400920
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500921 # The callback must always be called with a Connection instance as the
922 # first argument. It would probably be better to split this into
923 # separate tests for client and server side info callbacks so we could
924 # assert it is called with the right Connection instance. It would
925 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500926 notConnections = [
927 conn for (conn, where, ret) in called
928 if not isinstance(conn, Connection)]
929 self.assertEqual(
930 [], notConnections,
931 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400932
933
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400934 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400935 """
936 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400937 its :py:obj:`load_verify_locations` method with the given arguments.
938 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400939 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500940 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400941
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400942 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400943 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400944 # Require that the server certificate verify properly or the
945 # connection will fail.
946 clientContext.set_verify(
947 VERIFY_PEER,
948 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
949
950 clientSSL = Connection(clientContext, client)
951 clientSSL.set_connect_state()
952
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400953 serverContext = Context(TLSv1_METHOD)
954 serverContext.use_certificate(
955 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
956 serverContext.use_privatekey(
957 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
958
959 serverSSL = Connection(serverContext, server)
960 serverSSL.set_accept_state()
961
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400962 # Without load_verify_locations above, the handshake
963 # will fail:
964 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
965 # 'certificate verify failed')]
966 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400967
968 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400969 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400970
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500971
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400972 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400973 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400974 Verify that if path to a file containing a certificate is passed to
975 ``Context.load_verify_locations`` for the ``cafile`` parameter, that
976 certificate is used as a trust root for the purposes of verifying
977 connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400978 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400979 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400980 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400981 fObj.close()
982
983 self._load_verify_locations_test(cafile)
984
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400985
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400986 def test_load_verify_bytes_cafile(self):
987 """
988 :py:obj:`Context.load_verify_locations` accepts a file name as a
989 ``bytes`` instance and uses the certificates within for verification
990 purposes.
991 """
992 cafile = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
993 self._load_verify_cafile(cafile)
994
995
996 def test_load_verify_unicode_cafile(self):
997 """
998 :py:obj:`Context.load_verify_locations` accepts a file name as a
999 ``unicode`` instance and uses the certificates within for verification
1000 purposes.
1001 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001002 self._load_verify_cafile(
1003 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
1004 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001005
1006
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001007 def test_load_verify_invalid_file(self):
1008 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001009 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when passed a
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001010 non-existent cafile.
1011 """
1012 clientContext = Context(TLSv1_METHOD)
1013 self.assertRaises(
1014 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001015
1016
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001017 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001018 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001019 Verify that if path to a directory containing certificate files is
1020 passed to ``Context.load_verify_locations`` for the ``capath``
1021 parameter, those certificates are used as trust roots for the purposes
1022 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001023 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001024 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001025 # Hash values computed manually with c_rehash to avoid depending on
1026 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1027 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001028 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001029 cafile = join_bytes_or_unicode(capath, name)
1030 with open(cafile, 'w') as fObj:
1031 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001032
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001033 self._load_verify_locations_test(None, capath)
1034
1035
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001036 def test_load_verify_directory_bytes_capath(self):
1037 """
1038 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1039 ``bytes`` instance and uses the certificates within for verification
1040 purposes.
1041 """
1042 self._load_verify_directory_locations_capath(
1043 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
1044 )
1045
1046
1047 def test_load_verify_directory_unicode_capath(self):
1048 """
1049 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1050 ``unicode`` instance and uses the certificates within for verification
1051 purposes.
1052 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001053 self._load_verify_directory_locations_capath(
1054 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
1055 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001056
1057
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001058 def test_load_verify_locations_wrong_args(self):
1059 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001060 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if called with
1061 the wrong number of arguments or with non-:py:obj:`str` arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001062 """
1063 context = Context(TLSv1_METHOD)
1064 self.assertRaises(TypeError, context.load_verify_locations)
1065 self.assertRaises(TypeError, context.load_verify_locations, object())
1066 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
1067 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
1068
1069
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001070 if platform == "win32":
1071 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001072 "See LP#404343 and LP#404344."
1073 else:
1074 def test_set_default_verify_paths(self):
1075 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001076 :py:obj:`Context.set_default_verify_paths` causes the platform-specific CA
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001077 certificate locations to be used for verification purposes.
1078 """
1079 # Testing this requires a server with a certificate signed by one of
1080 # the CAs in the platform CA location. Getting one of those costs
1081 # money. Fortunately (or unfortunately, depending on your
1082 # perspective), it's easy to think of a public server on the
1083 # internet which has such a certificate. Connecting to the network
1084 # in a unit test is bad, but it's the only way I can think of to
1085 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001086
Alex Gaynorb586da32014-11-15 09:22:21 -08001087 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
1088 context = Context(TLSv1_METHOD)
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001089 context.set_default_verify_paths()
1090 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02001091 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001092 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001093
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001094 client = socket()
1095 client.connect(('verisign.com', 443))
1096 clientSSL = Connection(context, client)
1097 clientSSL.set_connect_state()
1098 clientSSL.do_handshake()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001099 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001100 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001101
1102
1103 def test_set_default_verify_paths_signature(self):
1104 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001105 :py:obj:`Context.set_default_verify_paths` takes no arguments and raises
1106 :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001107 """
1108 context = Context(TLSv1_METHOD)
1109 self.assertRaises(TypeError, context.set_default_verify_paths, None)
1110 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
1111 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001112
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001113
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001114 def test_add_extra_chain_cert_invalid_cert(self):
1115 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001116 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if called with
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001117 other than one argument or if called with an object which is not an
Jonathan Ballet648875f2011-07-16 14:14:58 +09001118 instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001119 """
1120 context = Context(TLSv1_METHOD)
1121 self.assertRaises(TypeError, context.add_extra_chain_cert)
1122 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
1123 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
1124
1125
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001126 def _handshake_test(self, serverContext, clientContext):
1127 """
1128 Verify that a client and server created with the given contexts can
1129 successfully handshake and communicate.
1130 """
1131 serverSocket, clientSocket = socket_pair()
1132
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001133 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001134 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001135
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001136 client = Connection(clientContext, clientSocket)
1137 client.set_connect_state()
1138
1139 # Make them talk to each other.
1140 # self._interactInMemory(client, server)
1141 for i in range(3):
1142 for s in [client, server]:
1143 try:
1144 s.do_handshake()
1145 except WantReadError:
1146 pass
1147
1148
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001149 def test_set_verify_callback_connection_argument(self):
1150 """
1151 The first argument passed to the verify callback is the
1152 :py:class:`Connection` instance for which verification is taking place.
1153 """
1154 serverContext = Context(TLSv1_METHOD)
1155 serverContext.use_privatekey(
1156 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1157 serverContext.use_certificate(
1158 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1159 serverConnection = Connection(serverContext, None)
1160
1161 class VerifyCallback(object):
1162 def callback(self, connection, *args):
1163 self.connection = connection
1164 return 1
1165
1166 verify = VerifyCallback()
1167 clientContext = Context(TLSv1_METHOD)
1168 clientContext.set_verify(VERIFY_PEER, verify.callback)
1169 clientConnection = Connection(clientContext, None)
1170 clientConnection.set_connect_state()
1171
1172 self._handshakeInMemory(clientConnection, serverConnection)
1173
1174 self.assertIdentical(verify.connection, clientConnection)
1175
1176
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001177 def test_set_verify_callback_exception(self):
1178 """
1179 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1180 exception, verification fails and the exception is propagated to the
1181 caller of :py:obj:`Connection.do_handshake`.
1182 """
1183 serverContext = Context(TLSv1_METHOD)
1184 serverContext.use_privatekey(
1185 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1186 serverContext.use_certificate(
1187 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1188
1189 clientContext = Context(TLSv1_METHOD)
1190 def verify_callback(*args):
1191 raise Exception("silly verify failure")
1192 clientContext.set_verify(VERIFY_PEER, verify_callback)
1193
1194 exc = self.assertRaises(
1195 Exception, self._handshake_test, serverContext, clientContext)
1196 self.assertEqual("silly verify failure", str(exc))
1197
1198
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001199 def test_add_extra_chain_cert(self):
1200 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001201 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509` instance to add to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001202 the certificate chain.
1203
Jonathan Ballet648875f2011-07-16 14:14:58 +09001204 See :py:obj:`_create_certificate_chain` for the details of the certificate
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001205 chain tested.
1206
1207 The chain is tested by starting a server with scert and connecting
1208 to it with a client which trusts cacert and requires verification to
1209 succeed.
1210 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001211 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001212 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1213
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001214 # Dump the CA certificate to a file because that's the only way to load
1215 # it as a trusted CA in the client context.
1216 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001217 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001218 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001219 fObj.close()
1220
1221 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001222 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001223 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001224 fObj.close()
1225
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001226 # Create the server context
1227 serverContext = Context(TLSv1_METHOD)
1228 serverContext.use_privatekey(skey)
1229 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001230 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001231 serverContext.add_extra_chain_cert(icert)
1232
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001233 # Create the client
1234 clientContext = Context(TLSv1_METHOD)
1235 clientContext.set_verify(
1236 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001237 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001238
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001239 # Try it out.
1240 self._handshake_test(serverContext, clientContext)
1241
1242
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001243 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001244 """
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001245 Verify that :py:obj:`Context.use_certificate_chain_file` reads a
1246 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001247
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001248 The chain is tested by starting a server with scert and connecting to
1249 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001250 succeed.
1251 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001252 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001253 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1254
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001255 makedirs(certdir)
1256
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001257 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1258 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001259
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001260 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001261 with open(chainFile, 'wb') as fObj:
1262 # Most specific to least general.
1263 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1264 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1265 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1266
1267 with open(caFile, 'w') as fObj:
1268 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001269
1270 serverContext = Context(TLSv1_METHOD)
1271 serverContext.use_certificate_chain_file(chainFile)
1272 serverContext.use_privatekey(skey)
1273
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001274 clientContext = Context(TLSv1_METHOD)
1275 clientContext.set_verify(
1276 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001277 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001278
1279 self._handshake_test(serverContext, clientContext)
1280
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001281
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001282 def test_use_certificate_chain_file_bytes(self):
1283 """
1284 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1285 an instance of ``bytes``) to specify additional certificates to use to
1286 construct and verify a trust chain.
1287 """
1288 self._use_certificate_chain_file_test(
1289 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
1290 )
1291
1292
1293 def test_use_certificate_chain_file_unicode(self):
1294 """
1295 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1296 an instance of ``unicode``) to specify additional certificates to use
1297 to construct and verify a trust chain.
1298 """
1299 self._use_certificate_chain_file_test(
1300 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
1301 )
1302
1303
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001304 def test_use_certificate_chain_file_wrong_args(self):
1305 """
1306 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1307 if passed zero or more than one argument or when passed a non-byte
1308 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error` when
1309 passed a bad chain file name (for example, the name of a file which does
1310 not exist).
1311 """
1312 context = Context(TLSv1_METHOD)
1313 self.assertRaises(TypeError, context.use_certificate_chain_file)
1314 self.assertRaises(TypeError, context.use_certificate_chain_file, object())
1315 self.assertRaises(TypeError, context.use_certificate_chain_file, b"foo", object())
1316
1317 self.assertRaises(Error, context.use_certificate_chain_file, self.mktemp())
1318
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001319 # XXX load_client_ca
1320 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001321
1322 def test_get_verify_mode_wrong_args(self):
1323 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001324 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001325 arguments.
1326 """
1327 context = Context(TLSv1_METHOD)
1328 self.assertRaises(TypeError, context.get_verify_mode, None)
1329
1330
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001331 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001332 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001333 :py:obj:`Context.get_verify_mode` returns the verify mode flags previously
1334 passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001335 """
1336 context = Context(TLSv1_METHOD)
1337 self.assertEquals(context.get_verify_mode(), 0)
1338 context.set_verify(
1339 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1340 self.assertEquals(
1341 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1342
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001343
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001344 if not PY3:
1345 def test_set_verify_mode_long(self):
1346 """
1347 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1348 type :py:obj:`long` as well as :py:obj:`int`.
1349 """
1350 context = Context(TLSv1_METHOD)
1351 self.assertEquals(context.get_verify_mode(), 0)
1352 context.set_verify(
1353 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None)
1354 self.assertEquals(
1355 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1356
1357
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001358 def test_load_tmp_dh_wrong_args(self):
1359 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001360 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
1361 number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001362 """
1363 context = Context(TLSv1_METHOD)
1364 self.assertRaises(TypeError, context.load_tmp_dh)
1365 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1366 self.assertRaises(TypeError, context.load_tmp_dh, object())
1367
1368
1369 def test_load_tmp_dh_missing_file(self):
1370 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001371 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the specified file
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001372 does not exist.
1373 """
1374 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001375 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001376
1377
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001378 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001379 """
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001380 Verify that calling ``Context.load_tmp_dh`` with the given filename
1381 does not raise an exception.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001382 """
1383 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001384 with open(dhfilename, "w") as dhfile:
1385 dhfile.write(dhparam)
1386
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001387 context.load_tmp_dh(dhfilename)
1388 # XXX What should I assert here? -exarkun
1389
1390
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001391 def test_load_tmp_dh_bytes(self):
1392 """
1393 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1394 specified file (given as ``bytes``).
1395 """
1396 self._load_tmp_dh_test(
1397 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
1398 )
1399
1400
1401 def test_load_tmp_dh_unicode(self):
1402 """
1403 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1404 specified file (given as ``unicode``).
1405 """
1406 self._load_tmp_dh_test(
1407 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
1408 )
1409
1410
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001411 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001412 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001413 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001414 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001415 """
1416 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001417 for curve in get_elliptic_curves():
1418 # The only easily "assertable" thing is that it does not raise an
1419 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001420 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001421
1422
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001423 def test_set_cipher_list_bytes(self):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001424 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001425 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
1426 ciphers which connections created with the context object will be able
1427 to choose from.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001428 """
1429 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001430 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001431 conn = Connection(context, None)
1432 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001433
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001434
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001435 def test_set_cipher_list_text(self):
1436 """
1437 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
1438 the ciphers which connections created with the context object will be
1439 able to choose from.
1440 """
1441 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -05001442 context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001443 conn = Connection(context, None)
1444 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
1445
1446
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001447 def test_set_cipher_list_wrong_args(self):
1448 """
Jean-Paul Calderone17044832014-01-18 10:20:11 -05001449 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
1450 passed zero arguments or more than one argument or when passed a
1451 non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001452 passed an incorrect cipher list string.
1453 """
1454 context = Context(TLSv1_METHOD)
1455 self.assertRaises(TypeError, context.set_cipher_list)
1456 self.assertRaises(TypeError, context.set_cipher_list, object())
1457 self.assertRaises(TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object())
1458
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001459 self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001460
1461
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001462 def test_set_session_cache_mode_wrong_args(self):
1463 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001464 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1465 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001466 """
1467 context = Context(TLSv1_METHOD)
1468 self.assertRaises(TypeError, context.set_session_cache_mode)
1469 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1470
1471
1472 def test_get_session_cache_mode_wrong_args(self):
1473 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001474 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1475 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001476 """
1477 context = Context(TLSv1_METHOD)
1478 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1479
1480
1481 def test_session_cache_mode(self):
1482 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001483 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1484 cached. The setting can be retrieved via
1485 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001486 """
1487 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001488 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001489 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1490 self.assertEqual(SESS_CACHE_OFF, off)
1491 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1492
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001493 if not PY3:
1494 def test_session_cache_mode_long(self):
1495 """
1496 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1497 of type :py:obj:`long` as well as :py:obj:`int`.
1498 """
1499 context = Context(TLSv1_METHOD)
1500 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1501 self.assertEqual(
1502 SESS_CACHE_BOTH, context.get_session_cache_mode())
1503
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001504
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001505 def test_get_cert_store(self):
1506 """
1507 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store` instance.
1508 """
1509 context = Context(TLSv1_METHOD)
1510 store = context.get_cert_store()
1511 self.assertIsInstance(store, X509Store)
1512
1513
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001514
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001515class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1516 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001517 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
1518 :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001519 """
1520 def test_wrong_args(self):
1521 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001522 :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001523 with other than one argument.
1524 """
1525 context = Context(TLSv1_METHOD)
1526 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1527 self.assertRaises(
1528 TypeError, context.set_tlsext_servername_callback, 1, 2)
1529
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001530
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001531 def test_old_callback_forgotten(self):
1532 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001533 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001534 callback, the one it replaces is dereferenced.
1535 """
1536 def callback(connection):
1537 pass
1538
1539 def replacement(connection):
1540 pass
1541
1542 context = Context(TLSv1_METHOD)
1543 context.set_tlsext_servername_callback(callback)
1544
1545 tracker = ref(callback)
1546 del callback
1547
1548 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001549
1550 # One run of the garbage collector happens to work on CPython. PyPy
1551 # doesn't collect the underlying object until a second run for whatever
1552 # reason. That's fine, it still demonstrates our code has properly
1553 # dropped the reference.
1554 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001555 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001556
1557 callback = tracker()
1558 if callback is not None:
1559 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001560 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001561 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001562
1563
1564 def test_no_servername(self):
1565 """
1566 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001567 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
1568 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001569 """
1570 args = []
1571 def servername(conn):
1572 args.append((conn, conn.get_servername()))
1573 context = Context(TLSv1_METHOD)
1574 context.set_tlsext_servername_callback(servername)
1575
1576 # Lose our reference to it. The Context is responsible for keeping it
1577 # alive now.
1578 del servername
1579 collect()
1580
1581 # Necessary to actually accept the connection
1582 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1583 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1584
1585 # Do a little connection to trigger the logic
1586 server = Connection(context, None)
1587 server.set_accept_state()
1588
1589 client = Connection(Context(TLSv1_METHOD), None)
1590 client.set_connect_state()
1591
1592 self._interactInMemory(server, client)
1593
1594 self.assertEqual([(server, None)], args)
1595
1596
1597 def test_servername(self):
1598 """
1599 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +09001600 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
1601 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001602 """
1603 args = []
1604 def servername(conn):
1605 args.append((conn, conn.get_servername()))
1606 context = Context(TLSv1_METHOD)
1607 context.set_tlsext_servername_callback(servername)
1608
1609 # Necessary to actually accept the connection
1610 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1611 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1612
1613 # Do a little connection to trigger the logic
1614 server = Connection(context, None)
1615 server.set_accept_state()
1616
1617 client = Connection(Context(TLSv1_METHOD), None)
1618 client.set_connect_state()
1619 client.set_tlsext_host_name(b("foo1.example.com"))
1620
1621 self._interactInMemory(server, client)
1622
1623 self.assertEqual([(server, b("foo1.example.com"))], args)
1624
1625
Cory Benfield84a121e2014-03-31 20:30:25 +01001626class NextProtoNegotiationTests(TestCase, _LoopbackMixin):
1627 """
1628 Test for Next Protocol Negotiation in PyOpenSSL.
1629 """
1630 def test_npn_success(self):
Cory Benfieldbe3e7b82014-05-10 09:48:55 +01001631 """
1632 Tests that clients and servers that agree on the negotiated next
1633 protocol can correct establish a connection, and that the agreed
1634 protocol is reported by the connections.
1635 """
1636 advertise_args = []
Cory Benfield84a121e2014-03-31 20:30:25 +01001637 select_args = []
1638 def advertise(conn):
1639 advertise_args.append((conn,))
Cory Benfieldbe3e7b82014-05-10 09:48:55 +01001640 return [b'http/1.1', b'spdy/2']
Cory Benfield84a121e2014-03-31 20:30:25 +01001641 def select(conn, options):
1642 select_args.append((conn, options))
Cory Benfieldbe3e7b82014-05-10 09:48:55 +01001643 return b'spdy/2'
Cory Benfield84a121e2014-03-31 20:30:25 +01001644
1645 server_context = Context(TLSv1_METHOD)
1646 server_context.set_npn_advertise_callback(advertise)
1647
1648 client_context = Context(TLSv1_METHOD)
1649 client_context.set_npn_select_callback(select)
1650
1651 # Necessary to actually accept the connection
1652 server_context.use_privatekey(
1653 load_privatekey(FILETYPE_PEM, server_key_pem))
1654 server_context.use_certificate(
1655 load_certificate(FILETYPE_PEM, server_cert_pem))
1656
1657 # Do a little connection to trigger the logic
1658 server = Connection(server_context, None)
1659 server.set_accept_state()
1660
1661 client = Connection(client_context, None)
1662 client.set_connect_state()
1663
1664 self._interactInMemory(server, client)
1665
1666 self.assertEqual([(server,)], advertise_args)
Cory Benfieldbe3e7b82014-05-10 09:48:55 +01001667 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001668
Cory Benfieldbe3e7b82014-05-10 09:48:55 +01001669 self.assertEqual(server.get_next_proto_negotiated(), b'spdy/2')
1670 self.assertEqual(client.get_next_proto_negotiated(), b'spdy/2')
Cory Benfield84a121e2014-03-31 20:30:25 +01001671
1672
1673 def test_npn_client_fail(self):
Cory Benfieldbe3e7b82014-05-10 09:48:55 +01001674 """
1675 Tests that when clients and servers cannot agree on what protocol to
1676 use next that the TLS connection does not get established.
1677 """
1678 advertise_args = []
Cory Benfield84a121e2014-03-31 20:30:25 +01001679 select_args = []
1680 def advertise(conn):
1681 advertise_args.append((conn,))
Cory Benfieldbe3e7b82014-05-10 09:48:55 +01001682 return [b'http/1.1', b'spdy/2']
Cory Benfield84a121e2014-03-31 20:30:25 +01001683 def select(conn, options):
1684 select_args.append((conn, options))
Cory Benfieldbe3e7b82014-05-10 09:48:55 +01001685 return b''
Cory Benfield84a121e2014-03-31 20:30:25 +01001686
1687 server_context = Context(TLSv1_METHOD)
1688 server_context.set_npn_advertise_callback(advertise)
1689
1690 client_context = Context(TLSv1_METHOD)
1691 client_context.set_npn_select_callback(select)
1692
1693 # Necessary to actually accept the connection
1694 server_context.use_privatekey(
1695 load_privatekey(FILETYPE_PEM, server_key_pem))
1696 server_context.use_certificate(
1697 load_certificate(FILETYPE_PEM, server_cert_pem))
1698
1699 # Do a little connection to trigger the logic
1700 server = Connection(server_context, None)
1701 server.set_accept_state()
1702
1703 client = Connection(client_context, None)
1704 client.set_connect_state()
1705
1706 # If the client doesn't return anything, the connection will fail.
1707 self.assertRaises(Error, self._interactInMemory, server, client)
1708
1709 self.assertEqual([(server,)], advertise_args)
Cory Benfieldbe3e7b82014-05-10 09:48:55 +01001710 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001711
1712
Cory Benfield0ea76e72015-03-22 09:05:28 +00001713 def test_npn_select_error(self):
1714 """
1715 Test that we can handle exceptions in the select callback. If select
1716 fails it should be fatal to the connection.
1717 """
1718 advertise_args = []
1719 def advertise(conn):
1720 advertise_args.append((conn,))
1721 return [b'http/1.1', b'spdy/2']
1722 def select(conn, options):
1723 raise TypeError
1724
1725 server_context = Context(TLSv1_METHOD)
1726 server_context.set_npn_advertise_callback(advertise)
1727
1728 client_context = Context(TLSv1_METHOD)
1729 client_context.set_npn_select_callback(select)
1730
1731 # Necessary to actually accept the connection
1732 server_context.use_privatekey(
1733 load_privatekey(FILETYPE_PEM, server_key_pem))
1734 server_context.use_certificate(
1735 load_certificate(FILETYPE_PEM, server_cert_pem))
1736
1737 # Do a little connection to trigger the logic
1738 server = Connection(server_context, None)
1739 server.set_accept_state()
1740
1741 client = Connection(client_context, None)
1742 client.set_connect_state()
1743
1744 # If the callback throws an exception it should be raised here.
1745 self.assertRaises(TypeError, self._interactInMemory, server, client)
1746 self.assertEqual([(server,)], advertise_args)
1747
1748
1749 def test_npn_advertise_error(self):
1750 """
1751 Test that we can handle exceptions in the advertise callback. If
1752 advertise fails no NPN is advertised to the client.
1753 """
1754 select_args = []
1755 def advertise(conn):
1756 raise TypeError
1757 def select(conn, options):
1758 select_args.append((conn, options))
1759 return b''
1760
1761 server_context = Context(TLSv1_METHOD)
1762 server_context.set_npn_advertise_callback(advertise)
1763
1764 client_context = Context(TLSv1_METHOD)
1765 client_context.set_npn_select_callback(select)
1766
1767 # Necessary to actually accept the connection
1768 server_context.use_privatekey(
1769 load_privatekey(FILETYPE_PEM, server_key_pem))
1770 server_context.use_certificate(
1771 load_certificate(FILETYPE_PEM, server_cert_pem))
1772
1773 # Do a little connection to trigger the logic
1774 server = Connection(server_context, None)
1775 server.set_accept_state()
1776
1777 client = Connection(client_context, None)
1778 client.set_connect_state()
1779
1780 # If the client doesn't return anything, the connection will fail.
1781 self.assertRaises(TypeError, self._interactInMemory, server, client)
1782 self.assertEqual([], select_args)
1783
1784
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001785
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001786class SessionTests(TestCase):
1787 """
1788 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1789 """
1790 def test_construction(self):
1791 """
1792 :py:class:`Session` can be constructed with no arguments, creating a new
1793 instance of that type.
1794 """
1795 new_session = Session()
1796 self.assertTrue(isinstance(new_session, Session))
1797
1798
1799 def test_construction_wrong_args(self):
1800 """
1801 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
1802 is raised.
1803 """
1804 self.assertRaises(TypeError, Session, 123)
1805 self.assertRaises(TypeError, Session, "hello")
1806 self.assertRaises(TypeError, Session, object())
1807
1808
1809
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001810class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05001811 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001812 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001813 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001814 # XXX get_peer_certificate -> None
1815 # XXX sock_shutdown
1816 # XXX master_key -> TypeError
1817 # XXX server_random -> TypeError
1818 # XXX state_string
1819 # XXX connect -> TypeError
1820 # XXX connect_ex -> TypeError
1821 # XXX set_connect_state -> TypeError
1822 # XXX set_accept_state -> TypeError
1823 # XXX renegotiate_pending
1824 # XXX do_handshake -> TypeError
1825 # XXX bio_read -> TypeError
1826 # XXX recv -> TypeError
1827 # XXX send -> TypeError
1828 # XXX bio_write -> TypeError
1829
Rick Deane15b1472009-07-09 15:53:42 -05001830 def test_type(self):
1831 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001832 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001833 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05001834 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001835 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05001836 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001837 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05001838
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001839
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001840 def test_get_context(self):
1841 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001842 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
1843 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001844 """
1845 context = Context(TLSv1_METHOD)
1846 connection = Connection(context, None)
1847 self.assertIdentical(connection.get_context(), context)
1848
1849
1850 def test_get_context_wrong_args(self):
1851 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001852 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001853 arguments.
1854 """
1855 connection = Connection(Context(TLSv1_METHOD), None)
1856 self.assertRaises(TypeError, connection.get_context, None)
1857
1858
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001859 def test_set_context_wrong_args(self):
1860 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001861 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
1862 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001863 than 1.
1864 """
1865 ctx = Context(TLSv1_METHOD)
1866 connection = Connection(ctx, None)
1867 self.assertRaises(TypeError, connection.set_context)
1868 self.assertRaises(TypeError, connection.set_context, object())
1869 self.assertRaises(TypeError, connection.set_context, "hello")
1870 self.assertRaises(TypeError, connection.set_context, 1)
1871 self.assertRaises(TypeError, connection.set_context, 1, 2)
1872 self.assertRaises(
1873 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
1874 self.assertIdentical(ctx, connection.get_context())
1875
1876
1877 def test_set_context(self):
1878 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001879 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001880 for the connection.
1881 """
1882 original = Context(SSLv23_METHOD)
1883 replacement = Context(TLSv1_METHOD)
1884 connection = Connection(original, None)
1885 connection.set_context(replacement)
1886 self.assertIdentical(replacement, connection.get_context())
1887 # Lose our references to the contexts, just in case the Connection isn't
1888 # properly managing its own contributions to their reference counts.
1889 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001890 collect()
1891
1892
1893 def test_set_tlsext_host_name_wrong_args(self):
1894 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001895 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001896 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09001897 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001898 """
1899 conn = Connection(Context(TLSv1_METHOD), None)
1900 self.assertRaises(TypeError, conn.set_tlsext_host_name)
1901 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
1902 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
1903 self.assertRaises(
1904 TypeError, conn.set_tlsext_host_name, b("with\0null"))
1905
Abraham Martinc5484ba2015-03-25 15:33:05 +00001906 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001907 # On Python 3.x, don't accidentally implicitly convert from text.
1908 self.assertRaises(
1909 TypeError,
1910 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001911
1912
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001913 def test_get_servername_wrong_args(self):
1914 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001915 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001916 arguments.
1917 """
1918 connection = Connection(Context(TLSv1_METHOD), None)
1919 self.assertRaises(TypeError, connection.get_servername, object())
1920 self.assertRaises(TypeError, connection.get_servername, 1)
1921 self.assertRaises(TypeError, connection.get_servername, "hello")
1922
1923
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001924 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001925 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001926 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001927 immediate read.
1928 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001929 connection = Connection(Context(TLSv1_METHOD), None)
1930 self.assertEquals(connection.pending(), 0)
1931
1932
1933 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001934 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001935 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001936 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001937 connection = Connection(Context(TLSv1_METHOD), None)
1938 self.assertRaises(TypeError, connection.pending, None)
1939
1940
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001941 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001942 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001943 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001944 argument or with the wrong number of arguments.
1945 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001946 connection = Connection(Context(TLSv1_METHOD), socket())
1947 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001948 self.assertRaises(TypeError, connection.connect)
1949 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001950
1951
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001952 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001953 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001954 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001955 connect method raises it.
1956 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001957 client = socket()
1958 context = Context(TLSv1_METHOD)
1959 clientSSL = Connection(context, client)
1960 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04001961 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001962
1963
1964 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001965 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001966 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001967 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001968 port = socket()
1969 port.bind(('', 0))
1970 port.listen(3)
1971
1972 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001973 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
1974 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001975
1976
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001977 if platform == "darwin":
1978 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
1979 else:
1980 def test_connect_ex(self):
1981 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001982 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001983 errno instead of raising an exception.
1984 """
1985 port = socket()
1986 port.bind(('', 0))
1987 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001988
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001989 clientSSL = Connection(Context(TLSv1_METHOD), socket())
1990 clientSSL.setblocking(False)
1991 result = clientSSL.connect_ex(port.getsockname())
1992 expected = (EINPROGRESS, EWOULDBLOCK)
1993 self.assertTrue(
1994 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001995
1996
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001997 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001998 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001999 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002000 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002001 connection = Connection(Context(TLSv1_METHOD), socket())
2002 self.assertRaises(TypeError, connection.accept, None)
2003
2004
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002005 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002006 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002007 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
2008 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002009 connection originated from.
2010 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002011 ctx = Context(TLSv1_METHOD)
2012 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2013 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002014 port = socket()
2015 portSSL = Connection(ctx, port)
2016 portSSL.bind(('', 0))
2017 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002018
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002019 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002020
2021 # Calling portSSL.getsockname() here to get the server IP address sounds
2022 # great, but frequently fails on Windows.
2023 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002024
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002025 serverSSL, address = portSSL.accept()
2026
2027 self.assertTrue(isinstance(serverSSL, Connection))
2028 self.assertIdentical(serverSSL.get_context(), ctx)
2029 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002030
2031
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002032 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002033 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002034 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002035 number of arguments or with arguments other than integers.
2036 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002037 connection = Connection(Context(TLSv1_METHOD), None)
2038 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04002039 self.assertRaises(TypeError, connection.get_shutdown, None)
2040 self.assertRaises(TypeError, connection.set_shutdown)
2041 self.assertRaises(TypeError, connection.set_shutdown, None)
2042 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002043
2044
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002045 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002046 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002047 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002048 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002049 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002050 self.assertFalse(server.shutdown())
2051 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002052 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002053 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
2054 client.shutdown()
2055 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
2056 self.assertRaises(ZeroReturnError, server.recv, 1024)
2057 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002058
2059
Paul Aurichc85e0862015-01-08 08:34:33 -08002060 def test_shutdown_closed(self):
2061 """
2062 If the underlying socket is closed, :py:obj:`Connection.shutdown` propagates the
2063 write error from the low level write call.
2064 """
2065 server, client = self._loopback()
2066 server.sock_shutdown(2)
2067 exc = self.assertRaises(SysCallError, server.shutdown)
2068 if platform == "win32":
2069 self.assertEqual(exc.args[0], ESHUTDOWN)
2070 else:
2071 self.assertEqual(exc.args[0], EPIPE)
2072
2073
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002074 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002075 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002076 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002077 process.
2078 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002079 connection = Connection(Context(TLSv1_METHOD), socket())
2080 connection.set_shutdown(RECEIVED_SHUTDOWN)
2081 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2082
2083
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002084 if not PY3:
2085 def test_set_shutdown_long(self):
2086 """
2087 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
2088 of type :py:obj:`long` as well as :py:obj:`int`.
2089 """
2090 connection = Connection(Context(TLSv1_METHOD), socket())
2091 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
2092 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2093
2094
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002095 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002096 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002097 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
2098 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002099 with any arguments.
2100 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002101 conn = Connection(Context(TLSv1_METHOD), None)
2102 self.assertRaises(TypeError, conn.get_app_data, None)
2103 self.assertRaises(TypeError, conn.set_app_data)
2104 self.assertRaises(TypeError, conn.set_app_data, None, None)
2105
2106
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002107 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002108 """
2109 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002110 :py:obj:`Connection.set_app_data` and later retrieved with
2111 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002112 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002113 conn = Connection(Context(TLSv1_METHOD), None)
2114 app_data = object()
2115 conn.set_app_data(app_data)
2116 self.assertIdentical(conn.get_app_data(), app_data)
2117
2118
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002119 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002120 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002121 :py:obj:`Connection.makefile` is not implemented and calling that method raises
2122 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002123 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002124 conn = Connection(Context(TLSv1_METHOD), None)
2125 self.assertRaises(NotImplementedError, conn.makefile)
2126
2127
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002128 def test_get_peer_cert_chain_wrong_args(self):
2129 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002130 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002131 arguments.
2132 """
2133 conn = Connection(Context(TLSv1_METHOD), None)
2134 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
2135 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
2136 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
2137 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
2138
2139
2140 def test_get_peer_cert_chain(self):
2141 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002142 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002143 the connected server returned for the certification verification.
2144 """
2145 chain = _create_certificate_chain()
2146 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2147
2148 serverContext = Context(TLSv1_METHOD)
2149 serverContext.use_privatekey(skey)
2150 serverContext.use_certificate(scert)
2151 serverContext.add_extra_chain_cert(icert)
2152 serverContext.add_extra_chain_cert(cacert)
2153 server = Connection(serverContext, None)
2154 server.set_accept_state()
2155
2156 # Create the client
2157 clientContext = Context(TLSv1_METHOD)
2158 clientContext.set_verify(VERIFY_NONE, verify_cb)
2159 client = Connection(clientContext, None)
2160 client.set_connect_state()
2161
2162 self._interactInMemory(client, server)
2163
2164 chain = client.get_peer_cert_chain()
2165 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002166 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002167 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002168 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002169 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002170 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002171 "Authority Certificate", chain[2].get_subject().CN)
2172
2173
2174 def test_get_peer_cert_chain_none(self):
2175 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002176 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002177 certificate chain.
2178 """
2179 ctx = Context(TLSv1_METHOD)
2180 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2181 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2182 server = Connection(ctx, None)
2183 server.set_accept_state()
2184 client = Connection(Context(TLSv1_METHOD), None)
2185 client.set_connect_state()
2186 self._interactInMemory(client, server)
2187 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002188
2189
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002190 def test_get_session_wrong_args(self):
2191 """
2192 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
2193 with any arguments.
2194 """
2195 ctx = Context(TLSv1_METHOD)
2196 server = Connection(ctx, None)
2197 self.assertRaises(TypeError, server.get_session, 123)
2198 self.assertRaises(TypeError, server.get_session, "hello")
2199 self.assertRaises(TypeError, server.get_session, object())
2200
2201
2202 def test_get_session_unconnected(self):
2203 """
2204 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
2205 an object which has not been connected.
2206 """
2207 ctx = Context(TLSv1_METHOD)
2208 server = Connection(ctx, None)
2209 session = server.get_session()
2210 self.assertIdentical(None, session)
2211
2212
2213 def test_server_get_session(self):
2214 """
2215 On the server side of a connection, :py:obj:`Connection.get_session`
2216 returns a :py:class:`Session` instance representing the SSL session for
2217 that connection.
2218 """
2219 server, client = self._loopback()
2220 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002221 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002222
2223
2224 def test_client_get_session(self):
2225 """
2226 On the client side of a connection, :py:obj:`Connection.get_session`
2227 returns a :py:class:`Session` instance representing the SSL session for
2228 that connection.
2229 """
2230 server, client = self._loopback()
2231 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002232 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002233
2234
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002235 def test_set_session_wrong_args(self):
2236 """
2237 If called with an object that is not an instance of :py:class:`Session`,
2238 or with other than one argument, :py:obj:`Connection.set_session` raises
2239 :py:obj:`TypeError`.
2240 """
2241 ctx = Context(TLSv1_METHOD)
2242 connection = Connection(ctx, None)
2243 self.assertRaises(TypeError, connection.set_session)
2244 self.assertRaises(TypeError, connection.set_session, 123)
2245 self.assertRaises(TypeError, connection.set_session, "hello")
2246 self.assertRaises(TypeError, connection.set_session, object())
2247 self.assertRaises(
2248 TypeError, connection.set_session, Session(), Session())
2249
2250
2251 def test_client_set_session(self):
2252 """
2253 :py:obj:`Connection.set_session`, when used prior to a connection being
2254 established, accepts a :py:class:`Session` instance and causes an
2255 attempt to re-use the session it represents when the SSL handshake is
2256 performed.
2257 """
2258 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2259 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2260 ctx = Context(TLSv1_METHOD)
2261 ctx.use_privatekey(key)
2262 ctx.use_certificate(cert)
2263 ctx.set_session_id("unity-test")
2264
2265 def makeServer(socket):
2266 server = Connection(ctx, socket)
2267 server.set_accept_state()
2268 return server
2269
2270 originalServer, originalClient = self._loopback(
2271 serverFactory=makeServer)
2272 originalSession = originalClient.get_session()
2273
2274 def makeClient(socket):
2275 client = self._loopbackClientFactory(socket)
2276 client.set_session(originalSession)
2277 return client
2278 resumedServer, resumedClient = self._loopback(
2279 serverFactory=makeServer,
2280 clientFactory=makeClient)
2281
2282 # This is a proxy: in general, we have no access to any unique
2283 # identifier for the session (new enough versions of OpenSSL expose a
2284 # hash which could be usable, but "new enough" is very, very new).
2285 # Instead, exploit the fact that the master key is re-used if the
2286 # session is re-used. As long as the master key for the two connections
2287 # is the same, the session was re-used!
2288 self.assertEqual(
2289 originalServer.master_key(), resumedServer.master_key())
2290
2291
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002292 def test_set_session_wrong_method(self):
2293 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002294 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
2295 instance associated with a context using a different SSL method than the
2296 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
2297 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002298 """
2299 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2300 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2301 ctx = Context(TLSv1_METHOD)
2302 ctx.use_privatekey(key)
2303 ctx.use_certificate(cert)
2304 ctx.set_session_id("unity-test")
2305
2306 def makeServer(socket):
2307 server = Connection(ctx, socket)
2308 server.set_accept_state()
2309 return server
2310
2311 originalServer, originalClient = self._loopback(
2312 serverFactory=makeServer)
2313 originalSession = originalClient.get_session()
2314
2315 def makeClient(socket):
2316 # Intentionally use a different, incompatible method here.
2317 client = Connection(Context(SSLv3_METHOD), socket)
2318 client.set_connect_state()
2319 client.set_session(originalSession)
2320 return client
2321
2322 self.assertRaises(
2323 Error,
2324 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2325
2326
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002327 def test_wantWriteError(self):
2328 """
2329 :py:obj:`Connection` methods which generate output raise
2330 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2331 fail indicating a should-write state.
2332 """
2333 client_socket, server_socket = socket_pair()
2334 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002335 # anything. Only write a single byte at a time so we can be sure we
2336 # completely fill the buffer. Even though the socket API is allowed to
2337 # signal a short write via its return value it seems this doesn't
2338 # always happen on all platforms (FreeBSD and OS X particular) for the
2339 # very last bit of available buffer space.
2340 msg = b"x"
2341 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002342 try:
2343 client_socket.send(msg)
2344 except error as e:
2345 if e.errno == EWOULDBLOCK:
2346 break
2347 raise
2348 else:
2349 self.fail(
2350 "Failed to fill socket buffer, cannot test BIO want write")
2351
2352 ctx = Context(TLSv1_METHOD)
2353 conn = Connection(ctx, client_socket)
2354 # Client's speak first, so make it an SSL client
2355 conn.set_connect_state()
2356 self.assertRaises(WantWriteError, conn.do_handshake)
2357
2358 # XXX want_read
2359
Fedor Brunner416f4a12014-03-28 13:18:38 +01002360 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002361 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002362 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2363 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002364 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002365 ctx = Context(TLSv1_METHOD)
2366 connection = Connection(ctx, None)
2367 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002368
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002369
Fedor Brunner416f4a12014-03-28 13:18:38 +01002370 def test_get_peer_finished_before_connect(self):
2371 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002372 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2373 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002374 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002375 ctx = Context(TLSv1_METHOD)
2376 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002377 self.assertEqual(connection.get_peer_finished(), None)
2378
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002379
Fedor Brunner416f4a12014-03-28 13:18:38 +01002380 def test_get_finished(self):
2381 """
2382 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002383 message send from client, or server. Finished messages are send during
2384 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002385 """
2386
Fedor Brunner5747b932014-03-05 14:22:34 +01002387 server, client = self._loopback()
2388
2389 self.assertNotEqual(server.get_finished(), None)
2390 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002391
Jean-Paul Calderoned979f232014-03-30 11:58:00 -04002392
Fedor Brunner416f4a12014-03-28 13:18:38 +01002393 def test_get_peer_finished(self):
2394 """
2395 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002396 message received from client, or server. Finished messages are send
2397 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002398 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002399 server, client = self._loopback()
2400
2401 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002402 self.assertTrue(len(server.get_peer_finished()) > 0)
2403
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002404
Fedor Brunner416f4a12014-03-28 13:18:38 +01002405 def test_tls_finished_message_symmetry(self):
2406 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002407 The TLS Finished message send by server must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002408 received by client.
2409
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002410 The TLS Finished message send by client must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002411 received by server.
2412 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002413 server, client = self._loopback()
2414
Fedor Brunner5747b932014-03-05 14:22:34 +01002415 self.assertEqual(server.get_finished(), client.get_peer_finished())
2416 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002417
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002418
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002419 def test_get_cipher_name_before_connect(self):
2420 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002421 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2422 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002423 """
2424 ctx = Context(TLSv1_METHOD)
2425 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002426 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002427
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002428
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002429 def test_get_cipher_name(self):
2430 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002431 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2432 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002433 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002434 server, client = self._loopback()
2435 server_cipher_name, client_cipher_name = \
2436 server.get_cipher_name(), client.get_cipher_name()
2437
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002438 self.assertIsInstance(server_cipher_name, text_type)
2439 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002440
2441 self.assertEqual(server_cipher_name, client_cipher_name)
2442
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002443
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002444 def test_get_cipher_version_before_connect(self):
2445 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002446 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2447 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002448 """
2449 ctx = Context(TLSv1_METHOD)
2450 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002451 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002452
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002453
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002454 def test_get_cipher_version(self):
2455 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002456 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2457 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002458 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002459 server, client = self._loopback()
2460 server_cipher_version, client_cipher_version = \
2461 server.get_cipher_version(), client.get_cipher_version()
2462
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002463 self.assertIsInstance(server_cipher_version, text_type)
2464 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002465
2466 self.assertEqual(server_cipher_version, client_cipher_version)
2467
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002468
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002469 def test_get_cipher_bits_before_connect(self):
2470 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002471 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2472 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002473 """
2474 ctx = Context(TLSv1_METHOD)
2475 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002476 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002477
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002478
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002479 def test_get_cipher_bits(self):
2480 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002481 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2482 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002483 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002484 server, client = self._loopback()
2485 server_cipher_bits, client_cipher_bits = \
2486 server.get_cipher_bits(), client.get_cipher_bits()
2487
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002488 self.assertIsInstance(server_cipher_bits, int)
2489 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002490
2491 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002492
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002493
2494
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002495class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002496 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002497 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002498 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002499 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002500 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002501 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002502 arguments.
2503 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002504 connection = Connection(Context(TLSv1_METHOD), None)
2505 self.assertRaises(TypeError, connection.get_cipher_list, None)
2506
2507
2508 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002509 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002510 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2511 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002512 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002513 connection = Connection(Context(TLSv1_METHOD), None)
2514 ciphers = connection.get_cipher_list()
2515 self.assertTrue(isinstance(ciphers, list))
2516 for cipher in ciphers:
2517 self.assertTrue(isinstance(cipher, str))
2518
2519
2520
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002521class ConnectionSendTests(TestCase, _LoopbackMixin):
2522 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002523 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002524 """
2525 def test_wrong_args(self):
2526 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002527 When called with arguments other than string argument for its first
2528 parameter or more than two arguments, :py:obj:`Connection.send` raises
2529 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002530 """
2531 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002532 self.assertRaises(TypeError, connection.send)
2533 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002534 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002535
2536
2537 def test_short_bytes(self):
2538 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002539 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002540 and returns the number of bytes sent.
2541 """
2542 server, client = self._loopback()
2543 count = server.send(b('xy'))
2544 self.assertEquals(count, 2)
2545 self.assertEquals(client.recv(2), b('xy'))
2546
Abraham Martinef063482015-03-25 14:06:24 +00002547
2548 def test_text(self):
2549 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002550 When passed a text, :py:obj:`Connection.send` transmits all of it and
2551 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002552 """
2553 server, client = self._loopback()
2554 with catch_warnings(record=True) as w:
2555 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002556 count = server.send(b"xy".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002557 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002558 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002559 WARNING_TYPE_EXPECTED
2560 ),
2561 str(w[-1].message)
2562 )
2563 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinef063482015-03-25 14:06:24 +00002564 self.assertEquals(count, 2)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002565 self.assertEquals(client.recv(2), b"xy")
Abraham Martinef063482015-03-25 14:06:24 +00002566
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002567 try:
2568 memoryview
2569 except NameError:
2570 "cannot test sending memoryview without memoryview"
2571 else:
2572 def test_short_memoryview(self):
2573 """
2574 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002575 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002576 bytes sent.
2577 """
2578 server, client = self._loopback()
2579 count = server.send(memoryview(b('xy')))
2580 self.assertEquals(count, 2)
2581 self.assertEquals(client.recv(2), b('xy'))
2582
2583
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002584 try:
2585 buffer
2586 except NameError:
2587 "cannot test sending buffer without buffer"
2588 else:
2589 def test_short_buffer(self):
2590 """
2591 When passed a buffer containing a small number of bytes,
2592 :py:obj:`Connection.send` transmits all of them and returns the number of
2593 bytes sent.
2594 """
2595 server, client = self._loopback()
2596 count = server.send(buffer(b('xy')))
2597 self.assertEquals(count, 2)
2598 self.assertEquals(client.recv(2), b('xy'))
2599
2600
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002601
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002602def _make_memoryview(size):
2603 """
2604 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2605 size.
2606 """
2607 return memoryview(bytearray(size))
2608
2609
2610
Cory Benfield62d10332014-06-15 10:03:41 +01002611class ConnectionRecvIntoTests(TestCase, _LoopbackMixin):
2612 """
2613 Tests for :py:obj:`Connection.recv_into`
2614 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002615 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002616 """
2617 Assert that when the given buffer is passed to
2618 ``Connection.recv_into``, whatever bytes are available to be received
2619 that fit into that buffer are written into that buffer.
2620 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002621 output_buffer = factory(5)
2622
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002623 server, client = self._loopback()
2624 server.send(b('xy'))
2625
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002626 self.assertEqual(client.recv_into(output_buffer), 2)
2627 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002628
2629
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002630 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002631 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002632 :py:obj:`Connection.recv_into` can be passed a ``bytearray`` instance
2633 and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002634 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002635 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002636
2637
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002638 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002639 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002640 Assert that when the given buffer is passed to ``Connection.recv_into``
2641 along with a value for ``nbytes`` that is less than the size of that
2642 buffer, only ``nbytes`` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002643 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002644 output_buffer = factory(10)
2645
Cory Benfield62d10332014-06-15 10:03:41 +01002646 server, client = self._loopback()
2647 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002648
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002649 self.assertEqual(client.recv_into(output_buffer, 5), 5)
2650 self.assertEqual(
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002651 output_buffer, bytearray(b('abcde\x00\x00\x00\x00\x00'))
2652 )
2653
2654
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002655 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002656 """
2657 When called with a ``bytearray`` instance,
2658 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter and
2659 doesn't copy in more than that number of bytes.
2660 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002661 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002662
2663
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002664 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002665 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002666 Assert that if there are more bytes available to be read from the
2667 receive buffer than would fit into the buffer passed to
2668 :py:obj:`Connection.recv_into`, only as many as fit are written into
2669 it.
Cory Benfield62d10332014-06-15 10:03:41 +01002670 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002671 output_buffer = factory(5)
2672
Cory Benfield62d10332014-06-15 10:03:41 +01002673 server, client = self._loopback()
2674 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002675
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002676 self.assertEqual(client.recv_into(output_buffer), 5)
2677 self.assertEqual(output_buffer, bytearray(b('abcde')))
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002678 rest = client.recv(5)
2679 self.assertEqual(b('fghij'), rest)
2680
2681
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002682 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002683 """
2684 When called with a ``bytearray`` instance,
2685 :py:obj:`Connection.recv_into` respects the size of the array and
2686 doesn't write more bytes into it than will fit.
2687 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002688 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002689
2690
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002691 def _really_doesnt_overfill_test(self, factory):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002692 """
2693 Assert that if the value given by ``nbytes`` is greater than the actual
2694 size of the output buffer passed to :py:obj:`Connection.recv_into`, the
2695 behavior is as if no value was given for ``nbytes`` at all.
2696 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002697 output_buffer = factory(5)
2698
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002699 server, client = self._loopback()
2700 server.send(b('abcdefghij'))
2701
2702 self.assertEqual(client.recv_into(output_buffer, 50), 5)
2703 self.assertEqual(output_buffer, bytearray(b('abcde')))
2704 rest = client.recv(5)
2705 self.assertEqual(b('fghij'), rest)
2706
2707
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002708 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002709 """
2710 When called with a ``bytearray`` instance and an ``nbytes`` value that
2711 is too large, :py:obj:`Connection.recv_into` respects the size of the
2712 array and not the ``nbytes`` value and doesn't write more bytes into
2713 the buffer than will fit.
2714 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002715 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002716
2717
Cory Benfield62d10332014-06-15 10:03:41 +01002718 try:
2719 memoryview
2720 except NameError:
2721 "cannot test recv_into memoryview without memoryview"
2722 else:
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002723 def test_memoryview_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002724 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002725 :py:obj:`Connection.recv_into` can be passed a ``memoryview``
2726 instance and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002727 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002728 self._no_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002729
2730
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002731 def test_memoryview_respects_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002732 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002733 When called with a ``memoryview`` instance,
2734 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter
2735 and doesn't copy more than that number of bytes in.
Cory Benfield62d10332014-06-15 10:03:41 +01002736 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002737 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002738
2739
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002740 def test_memoryview_doesnt_overfill(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002741 """
Jean-Paul Calderone8fd82552015-03-15 17:21:07 -04002742 When called with a ``memoryview`` instance,
2743 :py:obj:`Connection.recv_into` respects the size of the array and
2744 doesn't write more bytes into it than will fit.
Cory Benfield62d10332014-06-15 10:03:41 +01002745 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002746 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002747
2748
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002749 def test_memoryview_really_doesnt_overfill(self):
2750 """
2751 When called with a ``memoryview`` instance and an ``nbytes`` value
2752 that is too large, :py:obj:`Connection.recv_into` respects the size
2753 of the array and not the ``nbytes`` value and doesn't write more
2754 bytes into the buffer than will fit.
2755 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002756 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002757
2758
Cory Benfield62d10332014-06-15 10:03:41 +01002759
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002760class ConnectionSendallTests(TestCase, _LoopbackMixin):
2761 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002762 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002763 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002764 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002765 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002766 When called with arguments other than a string argument for its first
2767 parameter or with more than two arguments, :py:obj:`Connection.sendall`
2768 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002769 """
2770 connection = Connection(Context(TLSv1_METHOD), None)
2771 self.assertRaises(TypeError, connection.sendall)
2772 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002773 self.assertRaises(
2774 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002775
2776
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002777 def test_short(self):
2778 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002779 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002780 it.
2781 """
2782 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04002783 server.sendall(b('x'))
2784 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002785
2786
Abraham Martinef063482015-03-25 14:06:24 +00002787 def test_text(self):
2788 """
Jean-Paul Calderone93477422015-04-13 20:38:57 -04002789 :py:obj:`Connection.sendall` transmits all the content in the string
2790 passed to it raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00002791 """
2792 server, client = self._loopback()
2793 with catch_warnings(record=True) as w:
2794 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04002795 server.sendall(b"x".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002796 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002797 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002798 WARNING_TYPE_EXPECTED
2799 ),
2800 str(w[-1].message)
2801 )
2802 self.assertIs(w[-1].category, DeprecationWarning)
2803 self.assertEquals(client.recv(1), b"x")
Abraham Martinef063482015-03-25 14:06:24 +00002804
2805
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002806 try:
2807 memoryview
2808 except NameError:
2809 "cannot test sending memoryview without memoryview"
2810 else:
2811 def test_short_memoryview(self):
2812 """
2813 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002814 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002815 """
2816 server, client = self._loopback()
2817 server.sendall(memoryview(b('x')))
2818 self.assertEquals(client.recv(1), b('x'))
2819
2820
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002821 try:
2822 buffer
2823 except NameError:
2824 "cannot test sending buffers without buffers"
2825 else:
2826 def test_short_buffers(self):
2827 """
2828 When passed a buffer containing a small number of bytes,
2829 :py:obj:`Connection.sendall` transmits all of them.
2830 """
2831 server, client = self._loopback()
2832 server.sendall(buffer(b('x')))
2833 self.assertEquals(client.recv(1), b('x'))
2834
2835
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002836 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002837 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002838 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002839 it even if this requires multiple calls of an underlying write function.
2840 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002841 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04002842 # Should be enough, underlying SSL_write should only do 16k at a time.
2843 # On Windows, after 32k of bytes the write will block (forever - because
2844 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04002845 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002846 server.sendall(message)
2847 accum = []
2848 received = 0
2849 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04002850 data = client.recv(1024)
2851 accum.append(data)
2852 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04002853 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002854
2855
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002856 def test_closed(self):
2857 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002858 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002859 write error from the low level write call.
2860 """
2861 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04002862 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002863 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02002864 if platform == "win32":
2865 self.assertEqual(exc.args[0], ESHUTDOWN)
2866 else:
2867 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002868
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002869
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002870
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002871class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
2872 """
2873 Tests for SSL renegotiation APIs.
2874 """
2875 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002876 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002877 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002878 arguments.
2879 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002880 connection = Connection(Context(TLSv1_METHOD), None)
2881 self.assertRaises(TypeError, connection.renegotiate, None)
2882
2883
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002884 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002885 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002886 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002887 any arguments.
2888 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002889 connection = Connection(Context(TLSv1_METHOD), None)
2890 self.assertRaises(TypeError, connection.total_renegotiations, None)
2891
2892
2893 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002894 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002895 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002896 renegotiations have happened.
2897 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002898 connection = Connection(Context(TLSv1_METHOD), None)
2899 self.assertEquals(connection.total_renegotiations(), 0)
2900
2901
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002902# def test_renegotiate(self):
2903# """
2904# """
2905# server, client = self._loopback()
2906
2907# server.send("hello world")
2908# self.assertEquals(client.recv(len("hello world")), "hello world")
2909
2910# self.assertEquals(server.total_renegotiations(), 0)
2911# self.assertTrue(server.renegotiate())
2912
2913# server.setblocking(False)
2914# client.setblocking(False)
2915# while server.renegotiate_pending():
2916# client.do_handshake()
2917# server.do_handshake()
2918
2919# self.assertEquals(server.total_renegotiations(), 1)
2920
2921
2922
2923
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002924class ErrorTests(TestCase):
2925 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002926 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002927 """
2928 def test_type(self):
2929 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002930 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002931 """
2932 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05002933 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05002934
2935
2936
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002937class ConstantsTests(TestCase):
2938 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002939 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002940
2941 These are values defined by OpenSSL intended only to be used as flags to
2942 OpenSSL APIs. The only assertions it seems can be made about them is
2943 their values.
2944 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002945 # unittest.TestCase has no skip mechanism
2946 if OP_NO_QUERY_MTU is not None:
2947 def test_op_no_query_mtu(self):
2948 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002949 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002950 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002951 """
2952 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
2953 else:
2954 "OP_NO_QUERY_MTU 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_COOKIE_EXCHANGE is not None:
2958 def test_op_cookie_exchange(self):
2959 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002960 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002961 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002962 """
2963 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
2964 else:
2965 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002966
2967
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002968 if OP_NO_TICKET is not None:
2969 def test_op_no_ticket(self):
2970 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002971 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002972 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002973 """
2974 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04002975 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002976 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05002977
2978
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002979 if OP_NO_COMPRESSION is not None:
2980 def test_op_no_compression(self):
2981 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002982 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
2983 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002984 """
2985 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
2986 else:
2987 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
2988
2989
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002990 def test_sess_cache_off(self):
2991 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002992 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
2993 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002994 """
2995 self.assertEqual(0x0, SESS_CACHE_OFF)
2996
2997
2998 def test_sess_cache_client(self):
2999 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003000 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3001 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003002 """
3003 self.assertEqual(0x1, SESS_CACHE_CLIENT)
3004
3005
3006 def test_sess_cache_server(self):
3007 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003008 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3009 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003010 """
3011 self.assertEqual(0x2, SESS_CACHE_SERVER)
3012
3013
3014 def test_sess_cache_both(self):
3015 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003016 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3017 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003018 """
3019 self.assertEqual(0x3, SESS_CACHE_BOTH)
3020
3021
3022 def test_sess_cache_no_auto_clear(self):
3023 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003024 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3025 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3026 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003027 """
3028 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
3029
3030
3031 def test_sess_cache_no_internal_lookup(self):
3032 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003033 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3034 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3035 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003036 """
3037 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
3038
3039
3040 def test_sess_cache_no_internal_store(self):
3041 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003042 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3043 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3044 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003045 """
3046 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
3047
3048
3049 def test_sess_cache_no_internal(self):
3050 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003051 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3052 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
3053 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003054 """
3055 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
3056
3057
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04003058
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003059class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05003060 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003061 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003062 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003063 def _server(self, sock):
3064 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003065 Create a new server-side SSL :py:obj:`Connection` object wrapped around
3066 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003067 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003068 # Create the server side Connection. This is mostly setup boilerplate
3069 # - use TLSv1, use a particular certificate, etc.
3070 server_ctx = Context(TLSv1_METHOD)
3071 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
3072 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
3073 server_store = server_ctx.get_cert_store()
3074 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3075 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3076 server_ctx.check_privatekey()
3077 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003078 # Here the Connection is actually created. If None is passed as the 2nd
3079 # parameter, it indicates a memory BIO should be created.
3080 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003081 server_conn.set_accept_state()
3082 return server_conn
3083
3084
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003085 def _client(self, sock):
3086 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003087 Create a new client-side SSL :py:obj:`Connection` object wrapped around
3088 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003089 """
3090 # Now create the client side Connection. Similar boilerplate to the
3091 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003092 client_ctx = Context(TLSv1_METHOD)
3093 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
3094 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
3095 client_store = client_ctx.get_cert_store()
3096 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
3097 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
3098 client_ctx.check_privatekey()
3099 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003100 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003101 client_conn.set_connect_state()
3102 return client_conn
3103
3104
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003105 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003106 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003107 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003108 reading from the output of each and writing those bytes to the input of
3109 the other and in this way establish a connection and exchange
3110 application-level bytes with each other.
3111 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003112 server_conn = self._server(None)
3113 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003114
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003115 # There should be no key or nonces yet.
3116 self.assertIdentical(server_conn.master_key(), None)
3117 self.assertIdentical(server_conn.client_random(), None)
3118 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003119
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003120 # First, the handshake needs to happen. We'll deliver bytes back and
3121 # forth between the client and server until neither of them feels like
3122 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003123 self.assertIdentical(
3124 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003125
3126 # Now that the handshake is done, there should be a key and nonces.
3127 self.assertNotIdentical(server_conn.master_key(), None)
3128 self.assertNotIdentical(server_conn.client_random(), None)
3129 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04003130 self.assertEquals(server_conn.client_random(), client_conn.client_random())
3131 self.assertEquals(server_conn.server_random(), client_conn.server_random())
3132 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
3133 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003134
3135 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003136 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05003137
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003138 server_conn.write(important_message)
3139 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003140 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003141 (client_conn, important_message))
3142
3143 client_conn.write(important_message[::-1])
3144 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003145 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003146 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003147
3148
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003149 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003150 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003151 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003152
3153 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09003154 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003155 this test fails, there must be a problem outside the memory BIO
3156 code, as no memory BIO is involved here). Even though this isn't a
3157 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003158 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04003159 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003160
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003161 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05003162 client_conn.send(important_message)
3163 msg = server_conn.recv(1024)
3164 self.assertEqual(msg, important_message)
3165
3166 # Again in the other direction, just for fun.
3167 important_message = important_message[::-1]
3168 server_conn.send(important_message)
3169 msg = client_conn.recv(1024)
3170 self.assertEqual(msg, important_message)
3171
3172
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04003173 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003174 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003175 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
3176 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003177 """
3178 context = Context(SSLv3_METHOD)
3179 client = socket()
3180 clientSSL = Connection(context, client)
3181 self.assertRaises( TypeError, clientSSL.bio_read, 100)
3182 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04003183 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003184
3185
3186 def test_outgoingOverflow(self):
3187 """
3188 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09003189 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003190 returned and that many bytes from the beginning of the input can be
3191 read from the other end of the connection.
3192 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003193 server = self._server(None)
3194 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003195
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003196 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003197
3198 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003199 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003200 # Sanity check. We're trying to test what happens when the entire
3201 # input can't be sent. If the entire input was sent, this test is
3202 # meaningless.
3203 self.assertTrue(sent < size)
3204
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003205 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003206 self.assertIdentical(receiver, server)
3207
3208 # We can rely on all of these bytes being received at once because
3209 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
3210 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003211
3212
3213 def test_shutdown(self):
3214 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003215 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
3216 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003217 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003218 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003219 server.bio_shutdown()
3220 e = self.assertRaises(Error, server.recv, 1024)
3221 # We don't want WantReadError or ZeroReturnError or anything - it's a
3222 # handshake failure.
3223 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003224
3225
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003226 def test_unexpectedEndOfFile(self):
3227 """
3228 If the connection is lost before an orderly SSL shutdown occurs,
3229 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
3230 "Unexpected EOF".
3231 """
3232 server_conn, client_conn = self._loopback()
3233 client_conn.sock_shutdown(SHUT_RDWR)
3234 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
3235 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
3236
3237
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003238 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003239 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003240 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 -04003241
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003242 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003243 before the client and server are connected to each other. This
3244 function should specify a list of CAs for the server to send to the
3245 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09003246 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003247 times.
3248 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003249 server = self._server(None)
3250 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003251 self.assertEqual(client.get_client_ca_list(), [])
3252 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003253 ctx = server.get_context()
3254 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003255 self.assertEqual(client.get_client_ca_list(), [])
3256 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003257 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003258 self.assertEqual(client.get_client_ca_list(), expected)
3259 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003260
3261
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003262 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003263 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003264 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003265 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003266 """
3267 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003268 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
3269 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
3270 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003271
3272
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003273 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003274 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003275 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003276 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09003277 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003278 after the connection is set up.
3279 """
3280 def no_ca(ctx):
3281 ctx.set_client_ca_list([])
3282 return []
3283 self._check_client_ca_list(no_ca)
3284
3285
3286 def test_set_one_ca_list(self):
3287 """
3288 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003289 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003290 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003291 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003292 X509Name after the connection is set up.
3293 """
3294 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3295 cadesc = cacert.get_subject()
3296 def single_ca(ctx):
3297 ctx.set_client_ca_list([cadesc])
3298 return [cadesc]
3299 self._check_client_ca_list(single_ca)
3300
3301
3302 def test_set_multiple_ca_list(self):
3303 """
3304 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003305 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003306 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003307 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003308 X509Names after the connection is set up.
3309 """
3310 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3311 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3312
3313 sedesc = secert.get_subject()
3314 cldesc = clcert.get_subject()
3315
3316 def multiple_ca(ctx):
3317 L = [sedesc, cldesc]
3318 ctx.set_client_ca_list(L)
3319 return L
3320 self._check_client_ca_list(multiple_ca)
3321
3322
3323 def test_reset_ca_list(self):
3324 """
3325 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09003326 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003327 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003328 """
3329 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3330 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3331 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3332
3333 cadesc = cacert.get_subject()
3334 sedesc = secert.get_subject()
3335 cldesc = clcert.get_subject()
3336
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003337 def changed_ca(ctx):
3338 ctx.set_client_ca_list([sedesc, cldesc])
3339 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003340 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003341 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003342
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003343
3344 def test_mutated_ca_list(self):
3345 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003346 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003347 afterwards, this does not affect the list of CA names sent to the
3348 client.
3349 """
3350 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3351 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3352
3353 cadesc = cacert.get_subject()
3354 sedesc = secert.get_subject()
3355
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003356 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003357 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003358 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003359 L.append(sedesc)
3360 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003361 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003362
3363
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003364 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003365 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003366 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003367 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003368 """
3369 ctx = Context(TLSv1_METHOD)
3370 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003371 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003372 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003373 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003374
3375
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003376 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003377 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003378 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09003379 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003380 """
3381 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3382 cadesc = cacert.get_subject()
3383 def single_ca(ctx):
3384 ctx.add_client_ca(cacert)
3385 return [cadesc]
3386 self._check_client_ca_list(single_ca)
3387
3388
3389 def test_multiple_add_client_ca(self):
3390 """
3391 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09003392 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003393 """
3394 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3395 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3396
3397 cadesc = cacert.get_subject()
3398 sedesc = secert.get_subject()
3399
3400 def multiple_ca(ctx):
3401 ctx.add_client_ca(cacert)
3402 ctx.add_client_ca(secert)
3403 return [cadesc, sedesc]
3404 self._check_client_ca_list(multiple_ca)
3405
3406
3407 def test_set_and_add_client_ca(self):
3408 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003409 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
3410 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003411 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003412 """
3413 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3414 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3415 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3416
3417 cadesc = cacert.get_subject()
3418 sedesc = secert.get_subject()
3419 cldesc = clcert.get_subject()
3420
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003421 def mixed_set_add_ca(ctx):
3422 ctx.set_client_ca_list([cadesc, sedesc])
3423 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003424 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003425 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003426
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003427
3428 def test_set_after_add_client_ca(self):
3429 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003430 A call to :py:obj:`Context.set_client_ca_list` after a call to
3431 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003432 call with the names specified by the latter cal.
3433 """
3434 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3435 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3436 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3437
3438 cadesc = cacert.get_subject()
3439 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003440
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003441 def set_replaces_add_ca(ctx):
3442 ctx.add_client_ca(clcert)
3443 ctx.set_client_ca_list([cadesc])
3444 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003445 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003446 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003447
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003448
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003449
3450class ConnectionBIOTests(TestCase):
3451 """
3452 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3453 """
3454 def test_wantReadError(self):
3455 """
3456 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
3457 if there are no bytes available to be read from the BIO.
3458 """
3459 ctx = Context(TLSv1_METHOD)
3460 conn = Connection(ctx, None)
3461 self.assertRaises(WantReadError, conn.bio_read, 1024)
3462
3463
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003464 def test_buffer_size(self):
3465 """
3466 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3467 number of bytes to read and return.
3468 """
3469 ctx = Context(TLSv1_METHOD)
3470 conn = Connection(ctx, None)
3471 conn.set_connect_state()
3472 try:
3473 conn.do_handshake()
3474 except WantReadError:
3475 pass
3476 data = conn.bio_read(2)
3477 self.assertEqual(2, len(data))
3478
3479
3480 if not PY3:
3481 def test_buffer_size_long(self):
3482 """
3483 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3484 :py:obj:`long` as well as :py:obj:`int`.
3485 """
3486 ctx = Context(TLSv1_METHOD)
3487 conn = Connection(ctx, None)
3488 conn.set_connect_state()
3489 try:
3490 conn.do_handshake()
3491 except WantReadError:
3492 pass
3493 data = conn.bio_read(long(2))
3494 self.assertEqual(2, len(data))
3495
3496
3497
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003498
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003499class InfoConstantTests(TestCase):
3500 """
3501 Tests for assorted constants exposed for use in info callbacks.
3502 """
3503 def test_integers(self):
3504 """
3505 All of the info constants are integers.
3506
3507 This is a very weak test. It would be nice to have one that actually
3508 verifies that as certain info events happen, the value passed to the
3509 info callback matches up with the constant exposed by OpenSSL.SSL.
3510 """
3511 for const in [
3512 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3513 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3514 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3515 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3516 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
3517 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
3518
3519 self.assertTrue(isinstance(const, int))
3520
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003521
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003522if __name__ == '__main__':
3523 main()