blob: eae895e0fb0b3d15a3faa61e3488c8e0832f4f7f [file] [log] [blame]
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04001
2
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05003# Copyright (C) Jean-Paul Calderone
4# See LICENSE for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04005
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04006"""
Jonathan Ballet648875f2011-07-16 14:14:58 +09007Unit tests for :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04008"""
9
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -050010from gc import collect, get_referrers
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +020011from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE, ESHUTDOWN
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -040012from sys import platform, version_info, getfilesystemencoding
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070013from socket import SHUT_RDWR, error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040014from os import makedirs
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040015from os.path import join
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -040016from unittest import main
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040017from weakref import ref
Abraham Martinef063482015-03-25 14:06:24 +000018from warnings import catch_warnings, simplefilter
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050019
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -040020from six import PY3, text_type, u
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050021
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040022from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080023from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040024from OpenSSL.crypto import dump_privatekey, load_privatekey
25from OpenSSL.crypto import dump_certificate, load_certificate
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040026from OpenSSL.crypto import get_elliptic_curves
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040027
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040028from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
29from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040030from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040031from OpenSSL.SSL import (
32 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
33 TLSv1_1_METHOD, TLSv1_2_METHOD)
34from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040035from OpenSSL.SSL import (
36 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040037
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040038from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050039 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
40 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
41 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
42
43from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070044 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050045from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070046 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040047
Jean-Paul Calderone17eca482015-04-13 20:31:07 -040048from OpenSSL.test.util import WARNING_TYPE_EXPECTED, NON_ASCII, TestCase, b
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040049from OpenSSL.test.test_crypto import (
50 cleartextCertificatePEM, cleartextPrivateKeyPEM)
51from OpenSSL.test.test_crypto import (
52 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
53 root_cert_pem)
54
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050055try:
56 from OpenSSL.SSL import OP_NO_QUERY_MTU
57except ImportError:
58 OP_NO_QUERY_MTU = None
59try:
60 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
61except ImportError:
62 OP_COOKIE_EXCHANGE = None
63try:
64 from OpenSSL.SSL import OP_NO_TICKET
65except ImportError:
66 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040067
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040068try:
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -040069 from OpenSSL.SSL import OP_NO_COMPRESSION
70except ImportError:
71 OP_NO_COMPRESSION = None
72
73try:
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040074 from OpenSSL.SSL import MODE_RELEASE_BUFFERS
75except ImportError:
76 MODE_RELEASE_BUFFERS = None
77
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040078try:
79 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
80except ImportError:
81 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
82
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040083from OpenSSL.SSL import (
84 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
85 SSL_ST_OK, SSL_ST_RENEGOTIATE,
86 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
87 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
88 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
89 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040090
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040091# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
92# to use)
93dhparam = """\
94-----BEGIN DH PARAMETERS-----
95MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
96-----END DH PARAMETERS-----
97"""
98
99
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400100def join_bytes_or_unicode(prefix, suffix):
101 """
102 Join two path components of either ``bytes`` or ``unicode``.
103
104 The return type is the same as the type of ``prefix``.
105 """
106 # If the types are the same, nothing special is necessary.
107 if type(prefix) == type(suffix):
108 return join(prefix, suffix)
109
110 # Otherwise, coerce suffix to the type of prefix.
111 if isinstance(prefix, text_type):
112 return join(prefix, suffix.decode(getfilesystemencoding()))
113 else:
114 return join(prefix, suffix.encode(getfilesystemencoding()))
115
116
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400117def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400118 return ok
119
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400120
Rick Deanb1ccd562009-07-09 23:52:39 -0500121def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400122 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400123 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400124 """
125 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500126 port = socket()
127 port.bind(('', 0))
128 port.listen(1)
129 client = socket()
130 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400131 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400132 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500133 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500134
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400135 # Let's pass some unencrypted data to make sure our socket connection is
136 # fine. Just one byte, so we don't have to worry about buffers getting
137 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400138 server.send(b("x"))
139 assert client.recv(1024) == b("x")
140 client.send(b("y"))
141 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500142
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400143 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400144 server.setblocking(False)
145 client.setblocking(False)
146
Rick Deanb1ccd562009-07-09 23:52:39 -0500147 return (server, client)
148
149
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400150
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400151def handshake(client, server):
152 conns = [client, server]
153 while conns:
154 for conn in conns:
155 try:
156 conn.do_handshake()
157 except WantReadError:
158 pass
159 else:
160 conns.remove(conn)
161
162
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400163def _create_certificate_chain():
164 """
165 Construct and return a chain of certificates.
166
167 1. A new self-signed certificate authority certificate (cacert)
168 2. A new intermediate certificate signed by cacert (icert)
169 3. A new server certificate signed by icert (scert)
170 """
171 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
172
173 # Step 1
174 cakey = PKey()
175 cakey.generate_key(TYPE_RSA, 512)
176 cacert = X509()
177 cacert.get_subject().commonName = "Authority Certificate"
178 cacert.set_issuer(cacert.get_subject())
179 cacert.set_pubkey(cakey)
180 cacert.set_notBefore(b("20000101000000Z"))
181 cacert.set_notAfter(b("20200101000000Z"))
182 cacert.add_extensions([caext])
183 cacert.set_serial_number(0)
184 cacert.sign(cakey, "sha1")
185
186 # Step 2
187 ikey = PKey()
188 ikey.generate_key(TYPE_RSA, 512)
189 icert = X509()
190 icert.get_subject().commonName = "Intermediate Certificate"
191 icert.set_issuer(cacert.get_subject())
192 icert.set_pubkey(ikey)
193 icert.set_notBefore(b("20000101000000Z"))
194 icert.set_notAfter(b("20200101000000Z"))
195 icert.add_extensions([caext])
196 icert.set_serial_number(0)
197 icert.sign(cakey, "sha1")
198
199 # Step 3
200 skey = PKey()
201 skey.generate_key(TYPE_RSA, 512)
202 scert = X509()
203 scert.get_subject().commonName = "Server Certificate"
204 scert.set_issuer(icert.get_subject())
205 scert.set_pubkey(skey)
206 scert.set_notBefore(b("20000101000000Z"))
207 scert.set_notAfter(b("20200101000000Z"))
208 scert.add_extensions([
209 X509Extension(b('basicConstraints'), True, b('CA:false'))])
210 scert.set_serial_number(0)
211 scert.sign(ikey, "sha1")
212
213 return [(cakey, cacert), (ikey, icert), (skey, scert)]
214
215
216
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400217class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400218 """
219 Helper mixin which defines methods for creating a connected socket pair and
220 for forcing two connected SSL sockets to talk to each other via memory BIOs.
221 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500222 def _loopbackClientFactory(self, socket):
223 client = Connection(Context(TLSv1_METHOD), socket)
224 client.set_connect_state()
225 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400226
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500227
228 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400229 ctx = Context(TLSv1_METHOD)
230 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
231 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500232 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400233 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500234 return server
235
236
237 def _loopback(self, serverFactory=None, clientFactory=None):
238 if serverFactory is None:
239 serverFactory = self._loopbackServerFactory
240 if clientFactory is None:
241 clientFactory = self._loopbackClientFactory
242
243 (server, client) = socket_pair()
244 server = serverFactory(server)
245 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400246
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400247 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400248
249 server.setblocking(True)
250 client.setblocking(True)
251 return server, client
252
253
254 def _interactInMemory(self, client_conn, server_conn):
255 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900256 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400257 objects. Copy bytes back and forth between their send/receive buffers
258 for as long as there is anything to copy. When there is nothing more
Jonathan Ballet648875f2011-07-16 14:14:58 +0900259 to copy, return :py:obj:`None`. If one of them actually manages to deliver
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400260 some application bytes, return a two-tuple of the connection from which
261 the bytes were read and the bytes themselves.
262 """
263 wrote = True
264 while wrote:
265 # Loop until neither side has anything to say
266 wrote = False
267
268 # Copy stuff from each side's send buffer to the other side's
269 # receive buffer.
270 for (read, write) in [(client_conn, server_conn),
271 (server_conn, client_conn)]:
272
273 # Give the side a chance to generate some more bytes, or
274 # succeed.
275 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400276 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400277 except WantReadError:
278 # It didn't succeed, so we'll hope it generated some
279 # output.
280 pass
281 else:
282 # It did succeed, so we'll stop now and let the caller deal
283 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400284 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400285
286 while True:
287 # Keep copying as long as there's more stuff there.
288 try:
289 dirty = read.bio_read(4096)
290 except WantReadError:
291 # Okay, nothing more waiting to be sent. Stop
292 # processing this send buffer.
293 break
294 else:
295 # Keep track of the fact that someone generated some
296 # output.
297 wrote = True
298 write.bio_write(dirty)
299
300
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400301 def _handshakeInMemory(self, client_conn, server_conn):
Jean-Paul Calderoneb2b40782014-05-06 08:47:40 -0400302 """
303 Perform the TLS handshake between two :py:class:`Connection` instances
304 connected to each other via memory BIOs.
305 """
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400306 client_conn.set_connect_state()
307 server_conn.set_accept_state()
308
309 for conn in [client_conn, server_conn]:
310 try:
311 conn.do_handshake()
312 except WantReadError:
313 pass
314
315 self._interactInMemory(client_conn, server_conn)
316
317
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400318
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400319class VersionTests(TestCase):
320 """
321 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900322 :py:obj:`OpenSSL.SSL.SSLeay_version` and
323 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400324 """
325 def test_OPENSSL_VERSION_NUMBER(self):
326 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900327 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400328 byte and the patch, fix, minor, and major versions in the
329 nibbles above that.
330 """
331 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
332
333
334 def test_SSLeay_version(self):
335 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900336 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400337 one of a number of version strings based on that indicator.
338 """
339 versions = {}
340 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
341 SSLEAY_PLATFORM, SSLEAY_DIR]:
342 version = SSLeay_version(t)
343 versions[version] = t
344 self.assertTrue(isinstance(version, bytes))
345 self.assertEqual(len(versions), 5)
346
347
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400348
349class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400350 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900351 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400352 """
353 def test_method(self):
354 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900355 :py:obj:`Context` can be instantiated with one of :py:obj:`SSLv2_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400356 :py:obj:`SSLv3_METHOD`, :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
357 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400358 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400359 methods = [
360 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
361 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400362 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400363
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400364
365 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
366 for meth in maybe:
367 try:
368 Context(meth)
369 except (Error, ValueError):
370 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
371 # don't. Difficult to say in advance.
372 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400373
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400374 self.assertRaises(TypeError, Context, "")
375 self.assertRaises(ValueError, Context, 10)
376
377
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500378 if not PY3:
379 def test_method_long(self):
380 """
381 On Python 2 :py:class:`Context` accepts values of type
382 :py:obj:`long` as well as :py:obj:`int`.
383 """
384 Context(long(TLSv1_METHOD))
385
386
387
Rick Deane15b1472009-07-09 15:53:42 -0500388 def test_type(self):
389 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900390 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400391 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500392 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400393 self.assertIdentical(Context, ContextType)
394 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500395
396
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400397 def test_use_privatekey(self):
398 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900399 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400400 """
401 key = PKey()
402 key.generate_key(TYPE_RSA, 128)
403 ctx = Context(TLSv1_METHOD)
404 ctx.use_privatekey(key)
405 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400406
407
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800408 def test_use_privatekey_file_missing(self):
409 """
410 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error`
411 when passed the name of a file which does not exist.
412 """
413 ctx = Context(TLSv1_METHOD)
414 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
415
416
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400417 def _use_privatekey_file_test(self, pemfile, filetype):
418 """
419 Verify that calling ``Context.use_privatekey_file`` with the given
420 arguments does not raise an exception.
421 """
422 key = PKey()
423 key.generate_key(TYPE_RSA, 128)
424
425 with open(pemfile, "wt") as pem:
426 pem.write(
427 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
428 )
429
430 ctx = Context(TLSv1_METHOD)
431 ctx.use_privatekey_file(pemfile, filetype)
432
433
434 def test_use_privatekey_file_bytes(self):
435 """
436 A private key can be specified from a file by passing a ``bytes``
437 instance giving the file name to ``Context.use_privatekey_file``.
438 """
439 self._use_privatekey_file_test(
440 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
441 FILETYPE_PEM,
442 )
443
444
445 def test_use_privatekey_file_unicode(self):
446 """
447 A private key can be specified from a file by passing a ``unicode``
448 instance giving the file name to ``Context.use_privatekey_file``.
449 """
450 self._use_privatekey_file_test(
451 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
452 FILETYPE_PEM,
453 )
454
455
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500456 if not PY3:
457 def test_use_privatekey_file_long(self):
458 """
459 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
460 filetype of type :py:obj:`long` as well as :py:obj:`int`.
461 """
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400462 self._use_privatekey_file_test(self.mktemp(), long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500463
464
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800465 def test_use_certificate_wrong_args(self):
466 """
467 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
468 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as an
469 argument.
470 """
471 ctx = Context(TLSv1_METHOD)
472 self.assertRaises(TypeError, ctx.use_certificate)
473 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
474 self.assertRaises(TypeError, ctx.use_certificate, X509(), "hello, world")
475
476
477 def test_use_certificate_uninitialized(self):
478 """
479 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
480 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
481 initialized (ie, which does not actually have any certificate data).
482 """
483 ctx = Context(TLSv1_METHOD)
484 self.assertRaises(Error, ctx.use_certificate, X509())
485
486
487 def test_use_certificate(self):
488 """
489 :py:obj:`Context.use_certificate` sets the certificate which will be
490 used to identify connections created using the context.
491 """
492 # TODO
493 # Hard to assert anything. But we could set a privatekey then ask
494 # OpenSSL if the cert and key agree using check_privatekey. Then as
495 # long as check_privatekey works right we're good...
496 ctx = Context(TLSv1_METHOD)
497 ctx.use_certificate(load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
498
499
500 def test_use_certificate_file_wrong_args(self):
501 """
502 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
503 called with zero arguments or more than two arguments, or if the first
504 argument is not a byte string or the second argumnent is not an integer.
505 """
506 ctx = Context(TLSv1_METHOD)
507 self.assertRaises(TypeError, ctx.use_certificate_file)
508 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile", object())
509 self.assertRaises(
510 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM, object())
511 self.assertRaises(
512 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
513 self.assertRaises(
514 TypeError, ctx.use_certificate_file, b"somefile", object())
515
516
517 def test_use_certificate_file_missing(self):
518 """
519 :py:obj:`Context.use_certificate_file` raises
520 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does not
521 exist.
522 """
523 ctx = Context(TLSv1_METHOD)
524 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
525
526
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400527 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800528 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400529 Verify that calling ``Context.use_certificate_file`` with the given
530 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800531 """
532 # TODO
533 # Hard to assert anything. But we could set a privatekey then ask
534 # OpenSSL if the cert and key agree using check_privatekey. Then as
535 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400536 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800537 pem_file.write(cleartextCertificatePEM)
538
539 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400540 ctx.use_certificate_file(certificate_file)
541
542
543 def test_use_certificate_file_bytes(self):
544 """
545 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
546 ``bytes`` filename) which will be used to identify connections created
547 using the context.
548 """
549 filename = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
550 self._use_certificate_file_test(filename)
551
552
553 def test_use_certificate_file_unicode(self):
554 """
555 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
556 ``bytes`` filename) which will be used to identify connections created
557 using the context.
558 """
559 filename = self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
560 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800561
562
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500563 if not PY3:
564 def test_use_certificate_file_long(self):
565 """
566 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
567 filetype of type :py:obj:`long` as well as :py:obj:`int`.
568 """
569 pem_filename = self.mktemp()
570 with open(pem_filename, "wb") as pem_file:
571 pem_file.write(cleartextCertificatePEM)
572
573 ctx = Context(TLSv1_METHOD)
574 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
575
576
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500577 def test_check_privatekey_valid(self):
578 """
579 :py:obj:`Context.check_privatekey` returns :py:obj:`None` if the
580 :py:obj:`Context` instance has been configured to use a matched key and
581 certificate pair.
582 """
583 key = load_privatekey(FILETYPE_PEM, client_key_pem)
584 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
585 context = Context(TLSv1_METHOD)
586 context.use_privatekey(key)
587 context.use_certificate(cert)
588 self.assertIs(None, context.check_privatekey())
589
590
591 def test_check_privatekey_invalid(self):
592 """
593 :py:obj:`Context.check_privatekey` raises :py:obj:`Error` if the
594 :py:obj:`Context` instance has been configured to use a key and
595 certificate pair which don't relate to each other.
596 """
597 key = load_privatekey(FILETYPE_PEM, client_key_pem)
598 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
599 context = Context(TLSv1_METHOD)
600 context.use_privatekey(key)
601 context.use_certificate(cert)
602 self.assertRaises(Error, context.check_privatekey)
603
604
605 def test_check_privatekey_wrong_args(self):
606 """
607 :py:obj:`Context.check_privatekey` raises :py:obj:`TypeError` if called
608 with other than no arguments.
609 """
610 context = Context(TLSv1_METHOD)
611 self.assertRaises(TypeError, context.check_privatekey, object())
612
613
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400614 def test_set_app_data_wrong_args(self):
615 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900616 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called with other than
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400617 one argument.
618 """
619 context = Context(TLSv1_METHOD)
620 self.assertRaises(TypeError, context.set_app_data)
621 self.assertRaises(TypeError, context.set_app_data, None, None)
622
623
624 def test_get_app_data_wrong_args(self):
625 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900626 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400627 arguments.
628 """
629 context = Context(TLSv1_METHOD)
630 self.assertRaises(TypeError, context.get_app_data, None)
631
632
633 def test_app_data(self):
634 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900635 :py:obj:`Context.set_app_data` stores an object for later retrieval using
636 :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400637 """
638 app_data = object()
639 context = Context(TLSv1_METHOD)
640 context.set_app_data(app_data)
641 self.assertIdentical(context.get_app_data(), app_data)
642
643
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400644 def test_set_options_wrong_args(self):
645 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900646 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with the wrong
647 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400648 """
649 context = Context(TLSv1_METHOD)
650 self.assertRaises(TypeError, context.set_options)
651 self.assertRaises(TypeError, context.set_options, None)
652 self.assertRaises(TypeError, context.set_options, 1, None)
653
654
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500655 def test_set_options(self):
656 """
657 :py:obj:`Context.set_options` returns the new options value.
658 """
659 context = Context(TLSv1_METHOD)
660 options = context.set_options(OP_NO_SSLv2)
661 self.assertTrue(OP_NO_SSLv2 & options)
662
663
664 if not PY3:
665 def test_set_options_long(self):
666 """
667 On Python 2 :py:obj:`Context.set_options` accepts values of type
668 :py:obj:`long` as well as :py:obj:`int`.
669 """
670 context = Context(TLSv1_METHOD)
671 options = context.set_options(long(OP_NO_SSLv2))
672 self.assertTrue(OP_NO_SSLv2 & options)
673
674
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300675 def test_set_mode_wrong_args(self):
676 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400677 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with the wrong
678 number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300679 """
680 context = Context(TLSv1_METHOD)
681 self.assertRaises(TypeError, context.set_mode)
682 self.assertRaises(TypeError, context.set_mode, None)
683 self.assertRaises(TypeError, context.set_mode, 1, None)
684
685
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400686 if MODE_RELEASE_BUFFERS is not None:
687 def test_set_mode(self):
688 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400689 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the newly
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400690 set mode.
691 """
692 context = Context(TLSv1_METHOD)
693 self.assertTrue(
694 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500695
696 if not PY3:
697 def test_set_mode_long(self):
698 """
699 On Python 2 :py:obj:`Context.set_mode` accepts values of type
700 :py:obj:`long` as well as :py:obj:`int`.
701 """
702 context = Context(TLSv1_METHOD)
703 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
704 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400705 else:
706 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
707
708
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400709 def test_set_timeout_wrong_args(self):
710 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900711 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with the wrong
712 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400713 """
714 context = Context(TLSv1_METHOD)
715 self.assertRaises(TypeError, context.set_timeout)
716 self.assertRaises(TypeError, context.set_timeout, None)
717 self.assertRaises(TypeError, context.set_timeout, 1, None)
718
719
720 def test_get_timeout_wrong_args(self):
721 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900722 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400723 """
724 context = Context(TLSv1_METHOD)
725 self.assertRaises(TypeError, context.get_timeout, None)
726
727
728 def test_timeout(self):
729 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900730 :py:obj:`Context.set_timeout` sets the session timeout for all connections
731 created using the context object. :py:obj:`Context.get_timeout` retrieves this
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400732 value.
733 """
734 context = Context(TLSv1_METHOD)
735 context.set_timeout(1234)
736 self.assertEquals(context.get_timeout(), 1234)
737
738
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500739 if not PY3:
740 def test_timeout_long(self):
741 """
742 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
743 `long` as well as int.
744 """
745 context = Context(TLSv1_METHOD)
746 context.set_timeout(long(1234))
747 self.assertEquals(context.get_timeout(), 1234)
748
749
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400750 def test_set_verify_depth_wrong_args(self):
751 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900752 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called with the wrong
753 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400754 """
755 context = Context(TLSv1_METHOD)
756 self.assertRaises(TypeError, context.set_verify_depth)
757 self.assertRaises(TypeError, context.set_verify_depth, None)
758 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
759
760
761 def test_get_verify_depth_wrong_args(self):
762 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900763 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400764 """
765 context = Context(TLSv1_METHOD)
766 self.assertRaises(TypeError, context.get_verify_depth, None)
767
768
769 def test_verify_depth(self):
770 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900771 :py:obj:`Context.set_verify_depth` sets the number of certificates in a chain
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400772 to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900773 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400774 """
775 context = Context(TLSv1_METHOD)
776 context.set_verify_depth(11)
777 self.assertEquals(context.get_verify_depth(), 11)
778
779
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500780 if not PY3:
781 def test_verify_depth_long(self):
782 """
783 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
784 type `long` as well as int.
785 """
786 context = Context(TLSv1_METHOD)
787 context.set_verify_depth(long(11))
788 self.assertEquals(context.get_verify_depth(), 11)
789
790
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400791 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400792 """
793 Write a new private key out to a new file, encrypted using the given
794 passphrase. Return the path to the new file.
795 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400796 key = PKey()
797 key.generate_key(TYPE_RSA, 128)
798 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400799 fObj = open(pemFile, 'w')
800 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
801 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400802 fObj.close()
803 return pemFile
804
805
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400806 def test_set_passwd_cb_wrong_args(self):
807 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900808 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called with the
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400809 wrong arguments or with a non-callable first argument.
810 """
811 context = Context(TLSv1_METHOD)
812 self.assertRaises(TypeError, context.set_passwd_cb)
813 self.assertRaises(TypeError, context.set_passwd_cb, None)
814 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
815
816
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400817 def test_set_passwd_cb(self):
818 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900819 :py:obj:`Context.set_passwd_cb` accepts a callable which will be invoked when
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400820 a private key is loaded from an encrypted PEM.
821 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400822 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400823 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400824 calledWith = []
825 def passphraseCallback(maxlen, verify, extra):
826 calledWith.append((maxlen, verify, extra))
827 return passphrase
828 context = Context(TLSv1_METHOD)
829 context.set_passwd_cb(passphraseCallback)
830 context.use_privatekey_file(pemFile)
831 self.assertTrue(len(calledWith), 1)
832 self.assertTrue(isinstance(calledWith[0][0], int))
833 self.assertTrue(isinstance(calledWith[0][1], int))
834 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400835
836
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400837 def test_passwd_callback_exception(self):
838 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900839 :py:obj:`Context.use_privatekey_file` propagates any exception raised by the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400840 passphrase callback.
841 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400842 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400843 def passphraseCallback(maxlen, verify, extra):
844 raise RuntimeError("Sorry, I am a fail.")
845
846 context = Context(TLSv1_METHOD)
847 context.set_passwd_cb(passphraseCallback)
848 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
849
850
851 def test_passwd_callback_false(self):
852 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900853 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400854 passphrase callback returns a false value.
855 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400856 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400857 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500858 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400859
860 context = Context(TLSv1_METHOD)
861 context.set_passwd_cb(passphraseCallback)
862 self.assertRaises(Error, context.use_privatekey_file, pemFile)
863
864
865 def test_passwd_callback_non_string(self):
866 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900867 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400868 passphrase callback returns a true non-string value.
869 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400870 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400871 def passphraseCallback(maxlen, verify, extra):
872 return 10
873
874 context = Context(TLSv1_METHOD)
875 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800876 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400877
878
879 def test_passwd_callback_too_long(self):
880 """
881 If the passphrase returned by the passphrase callback returns a string
882 longer than the indicated maximum length, it is truncated.
883 """
884 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400885 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400886 pemFile = self._write_encrypted_pem(passphrase)
887 def passphraseCallback(maxlen, verify, extra):
888 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400889 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400890
891 context = Context(TLSv1_METHOD)
892 context.set_passwd_cb(passphraseCallback)
893 # This shall succeed because the truncated result is the correct
894 # passphrase.
895 context.use_privatekey_file(pemFile)
896
897
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400898 def test_set_info_callback(self):
899 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900900 :py:obj:`Context.set_info_callback` accepts a callable which will be invoked
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400901 when certain information about an SSL connection is available.
902 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500903 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400904
905 clientSSL = Connection(Context(TLSv1_METHOD), client)
906 clientSSL.set_connect_state()
907
908 called = []
909 def info(conn, where, ret):
910 called.append((conn, where, ret))
911 context = Context(TLSv1_METHOD)
912 context.set_info_callback(info)
913 context.use_certificate(
914 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
915 context.use_privatekey(
916 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
917
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400918 serverSSL = Connection(context, server)
919 serverSSL.set_accept_state()
920
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500921 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400922
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500923 # The callback must always be called with a Connection instance as the
924 # first argument. It would probably be better to split this into
925 # separate tests for client and server side info callbacks so we could
926 # assert it is called with the right Connection instance. It would
927 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500928 notConnections = [
929 conn for (conn, where, ret) in called
930 if not isinstance(conn, Connection)]
931 self.assertEqual(
932 [], notConnections,
933 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400934
935
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400936 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400937 """
938 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400939 its :py:obj:`load_verify_locations` method with the given arguments.
940 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400941 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500942 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400943
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400944 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400945 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400946 # Require that the server certificate verify properly or the
947 # connection will fail.
948 clientContext.set_verify(
949 VERIFY_PEER,
950 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
951
952 clientSSL = Connection(clientContext, client)
953 clientSSL.set_connect_state()
954
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400955 serverContext = Context(TLSv1_METHOD)
956 serverContext.use_certificate(
957 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
958 serverContext.use_privatekey(
959 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
960
961 serverSSL = Connection(serverContext, server)
962 serverSSL.set_accept_state()
963
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400964 # Without load_verify_locations above, the handshake
965 # will fail:
966 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
967 # 'certificate verify failed')]
968 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400969
970 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400971 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400972
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500973
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400974 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400975 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400976 Verify that if path to a file containing a certificate is passed to
977 ``Context.load_verify_locations`` for the ``cafile`` parameter, that
978 certificate is used as a trust root for the purposes of verifying
979 connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400980 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400981 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400982 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400983 fObj.close()
984
985 self._load_verify_locations_test(cafile)
986
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400987
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400988 def test_load_verify_bytes_cafile(self):
989 """
990 :py:obj:`Context.load_verify_locations` accepts a file name as a
991 ``bytes`` instance and uses the certificates within for verification
992 purposes.
993 """
994 cafile = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
995 self._load_verify_cafile(cafile)
996
997
998 def test_load_verify_unicode_cafile(self):
999 """
1000 :py:obj:`Context.load_verify_locations` accepts a file name as a
1001 ``unicode`` instance and uses the certificates within for verification
1002 purposes.
1003 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001004 self._load_verify_cafile(
1005 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
1006 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001007
1008
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001009 def test_load_verify_invalid_file(self):
1010 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001011 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when passed a
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001012 non-existent cafile.
1013 """
1014 clientContext = Context(TLSv1_METHOD)
1015 self.assertRaises(
1016 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001017
1018
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001019 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001020 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001021 Verify that if path to a directory containing certificate files is
1022 passed to ``Context.load_verify_locations`` for the ``capath``
1023 parameter, those certificates are used as trust roots for the purposes
1024 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001025 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001026 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001027 # Hash values computed manually with c_rehash to avoid depending on
1028 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1029 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001030 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001031 cafile = join_bytes_or_unicode(capath, name)
1032 with open(cafile, 'w') as fObj:
1033 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001034
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001035 self._load_verify_locations_test(None, capath)
1036
1037
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001038 def test_load_verify_directory_bytes_capath(self):
1039 """
1040 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1041 ``bytes`` instance and uses the certificates within for verification
1042 purposes.
1043 """
1044 self._load_verify_directory_locations_capath(
1045 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
1046 )
1047
1048
1049 def test_load_verify_directory_unicode_capath(self):
1050 """
1051 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1052 ``unicode`` instance and uses the certificates within for verification
1053 purposes.
1054 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001055 self._load_verify_directory_locations_capath(
1056 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
1057 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001058
1059
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001060 def test_load_verify_locations_wrong_args(self):
1061 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001062 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if called with
1063 the wrong number of arguments or with non-:py:obj:`str` arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001064 """
1065 context = Context(TLSv1_METHOD)
1066 self.assertRaises(TypeError, context.load_verify_locations)
1067 self.assertRaises(TypeError, context.load_verify_locations, object())
1068 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
1069 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
1070
1071
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001072 if platform == "win32":
1073 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001074 "See LP#404343 and LP#404344."
1075 else:
1076 def test_set_default_verify_paths(self):
1077 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001078 :py:obj:`Context.set_default_verify_paths` causes the platform-specific CA
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001079 certificate locations to be used for verification purposes.
1080 """
1081 # Testing this requires a server with a certificate signed by one of
1082 # the CAs in the platform CA location. Getting one of those costs
1083 # money. Fortunately (or unfortunately, depending on your
1084 # perspective), it's easy to think of a public server on the
1085 # internet which has such a certificate. Connecting to the network
1086 # in a unit test is bad, but it's the only way I can think of to
1087 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001088
Alex Gaynorb586da32014-11-15 09:22:21 -08001089 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
1090 context = Context(TLSv1_METHOD)
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001091 context.set_default_verify_paths()
1092 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02001093 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001094 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001095
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001096 client = socket()
1097 client.connect(('verisign.com', 443))
1098 clientSSL = Connection(context, client)
1099 clientSSL.set_connect_state()
1100 clientSSL.do_handshake()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001101 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001102 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001103
1104
1105 def test_set_default_verify_paths_signature(self):
1106 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001107 :py:obj:`Context.set_default_verify_paths` takes no arguments and raises
1108 :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001109 """
1110 context = Context(TLSv1_METHOD)
1111 self.assertRaises(TypeError, context.set_default_verify_paths, None)
1112 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
1113 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001114
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001115
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001116 def test_add_extra_chain_cert_invalid_cert(self):
1117 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001118 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if called with
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001119 other than one argument or if called with an object which is not an
Jonathan Ballet648875f2011-07-16 14:14:58 +09001120 instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001121 """
1122 context = Context(TLSv1_METHOD)
1123 self.assertRaises(TypeError, context.add_extra_chain_cert)
1124 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
1125 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
1126
1127
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001128 def _handshake_test(self, serverContext, clientContext):
1129 """
1130 Verify that a client and server created with the given contexts can
1131 successfully handshake and communicate.
1132 """
1133 serverSocket, clientSocket = socket_pair()
1134
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001135 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001136 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001137
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001138 client = Connection(clientContext, clientSocket)
1139 client.set_connect_state()
1140
1141 # Make them talk to each other.
1142 # self._interactInMemory(client, server)
1143 for i in range(3):
1144 for s in [client, server]:
1145 try:
1146 s.do_handshake()
1147 except WantReadError:
1148 pass
1149
1150
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001151 def test_set_verify_callback_connection_argument(self):
1152 """
1153 The first argument passed to the verify callback is the
1154 :py:class:`Connection` instance for which verification is taking place.
1155 """
1156 serverContext = Context(TLSv1_METHOD)
1157 serverContext.use_privatekey(
1158 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1159 serverContext.use_certificate(
1160 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1161 serverConnection = Connection(serverContext, None)
1162
1163 class VerifyCallback(object):
1164 def callback(self, connection, *args):
1165 self.connection = connection
1166 return 1
1167
1168 verify = VerifyCallback()
1169 clientContext = Context(TLSv1_METHOD)
1170 clientContext.set_verify(VERIFY_PEER, verify.callback)
1171 clientConnection = Connection(clientContext, None)
1172 clientConnection.set_connect_state()
1173
1174 self._handshakeInMemory(clientConnection, serverConnection)
1175
1176 self.assertIdentical(verify.connection, clientConnection)
1177
1178
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001179 def test_set_verify_callback_exception(self):
1180 """
1181 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1182 exception, verification fails and the exception is propagated to the
1183 caller of :py:obj:`Connection.do_handshake`.
1184 """
1185 serverContext = Context(TLSv1_METHOD)
1186 serverContext.use_privatekey(
1187 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1188 serverContext.use_certificate(
1189 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1190
1191 clientContext = Context(TLSv1_METHOD)
1192 def verify_callback(*args):
1193 raise Exception("silly verify failure")
1194 clientContext.set_verify(VERIFY_PEER, verify_callback)
1195
1196 exc = self.assertRaises(
1197 Exception, self._handshake_test, serverContext, clientContext)
1198 self.assertEqual("silly verify failure", str(exc))
1199
1200
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001201 def test_add_extra_chain_cert(self):
1202 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001203 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509` instance to add to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001204 the certificate chain.
1205
Jonathan Ballet648875f2011-07-16 14:14:58 +09001206 See :py:obj:`_create_certificate_chain` for the details of the certificate
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001207 chain tested.
1208
1209 The chain is tested by starting a server with scert and connecting
1210 to it with a client which trusts cacert and requires verification to
1211 succeed.
1212 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001213 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001214 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1215
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001216 # Dump the CA certificate to a file because that's the only way to load
1217 # it as a trusted CA in the client context.
1218 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001219 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001220 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001221 fObj.close()
1222
1223 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001224 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001225 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001226 fObj.close()
1227
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001228 # Create the server context
1229 serverContext = Context(TLSv1_METHOD)
1230 serverContext.use_privatekey(skey)
1231 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001232 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001233 serverContext.add_extra_chain_cert(icert)
1234
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001235 # Create the client
1236 clientContext = Context(TLSv1_METHOD)
1237 clientContext.set_verify(
1238 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001239 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001240
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001241 # Try it out.
1242 self._handshake_test(serverContext, clientContext)
1243
1244
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001245 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001246 """
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001247 Verify that :py:obj:`Context.use_certificate_chain_file` reads a
1248 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001249
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001250 The chain is tested by starting a server with scert and connecting to
1251 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001252 succeed.
1253 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001254 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001255 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1256
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001257 makedirs(certdir)
1258
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001259 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1260 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001261
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001262 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001263 with open(chainFile, 'wb') as fObj:
1264 # Most specific to least general.
1265 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1266 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1267 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1268
1269 with open(caFile, 'w') as fObj:
1270 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001271
1272 serverContext = Context(TLSv1_METHOD)
1273 serverContext.use_certificate_chain_file(chainFile)
1274 serverContext.use_privatekey(skey)
1275
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001276 clientContext = Context(TLSv1_METHOD)
1277 clientContext.set_verify(
1278 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001279 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001280
1281 self._handshake_test(serverContext, clientContext)
1282
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001283
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001284 def test_use_certificate_chain_file_bytes(self):
1285 """
1286 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1287 an instance of ``bytes``) to specify additional certificates to use to
1288 construct and verify a trust chain.
1289 """
1290 self._use_certificate_chain_file_test(
1291 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
1292 )
1293
1294
1295 def test_use_certificate_chain_file_unicode(self):
1296 """
1297 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1298 an instance of ``unicode``) to specify additional certificates to use
1299 to construct and verify a trust chain.
1300 """
1301 self._use_certificate_chain_file_test(
1302 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
1303 )
1304
1305
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001306 def test_use_certificate_chain_file_wrong_args(self):
1307 """
1308 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1309 if passed zero or more than one argument or when passed a non-byte
1310 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error` when
1311 passed a bad chain file name (for example, the name of a file which does
1312 not exist).
1313 """
1314 context = Context(TLSv1_METHOD)
1315 self.assertRaises(TypeError, context.use_certificate_chain_file)
1316 self.assertRaises(TypeError, context.use_certificate_chain_file, object())
1317 self.assertRaises(TypeError, context.use_certificate_chain_file, b"foo", object())
1318
1319 self.assertRaises(Error, context.use_certificate_chain_file, self.mktemp())
1320
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001321 # XXX load_client_ca
1322 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001323
1324 def test_get_verify_mode_wrong_args(self):
1325 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001326 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001327 arguments.
1328 """
1329 context = Context(TLSv1_METHOD)
1330 self.assertRaises(TypeError, context.get_verify_mode, None)
1331
1332
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001333 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001334 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001335 :py:obj:`Context.get_verify_mode` returns the verify mode flags previously
1336 passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001337 """
1338 context = Context(TLSv1_METHOD)
1339 self.assertEquals(context.get_verify_mode(), 0)
1340 context.set_verify(
1341 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1342 self.assertEquals(
1343 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1344
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001345
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001346 if not PY3:
1347 def test_set_verify_mode_long(self):
1348 """
1349 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1350 type :py:obj:`long` as well as :py:obj:`int`.
1351 """
1352 context = Context(TLSv1_METHOD)
1353 self.assertEquals(context.get_verify_mode(), 0)
1354 context.set_verify(
1355 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None)
1356 self.assertEquals(
1357 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1358
1359
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001360 def test_load_tmp_dh_wrong_args(self):
1361 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001362 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
1363 number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001364 """
1365 context = Context(TLSv1_METHOD)
1366 self.assertRaises(TypeError, context.load_tmp_dh)
1367 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1368 self.assertRaises(TypeError, context.load_tmp_dh, object())
1369
1370
1371 def test_load_tmp_dh_missing_file(self):
1372 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001373 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the specified file
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001374 does not exist.
1375 """
1376 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001377 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001378
1379
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001380 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001381 """
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001382 Verify that calling ``Context.load_tmp_dh`` with the given filename
1383 does not raise an exception.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001384 """
1385 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001386 with open(dhfilename, "w") as dhfile:
1387 dhfile.write(dhparam)
1388
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001389 context.load_tmp_dh(dhfilename)
1390 # XXX What should I assert here? -exarkun
1391
1392
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001393 def test_load_tmp_dh_bytes(self):
1394 """
1395 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1396 specified file (given as ``bytes``).
1397 """
1398 self._load_tmp_dh_test(
1399 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
1400 )
1401
1402
1403 def test_load_tmp_dh_unicode(self):
1404 """
1405 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1406 specified file (given as ``unicode``).
1407 """
1408 self._load_tmp_dh_test(
1409 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
1410 )
1411
1412
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001413 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001414 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001415 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001416 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001417 """
1418 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001419 for curve in get_elliptic_curves():
1420 # The only easily "assertable" thing is that it does not raise an
1421 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001422 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001423
1424
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001425 def test_set_cipher_list_bytes(self):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001426 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001427 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
1428 ciphers which connections created with the context object will be able
1429 to choose from.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001430 """
1431 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001432 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001433 conn = Connection(context, None)
1434 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001435
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001436
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001437 def test_set_cipher_list_text(self):
1438 """
1439 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
1440 the ciphers which connections created with the context object will be
1441 able to choose from.
1442 """
1443 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -05001444 context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001445 conn = Connection(context, None)
1446 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
1447
1448
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001449 def test_set_cipher_list_wrong_args(self):
1450 """
Jean-Paul Calderone17044832014-01-18 10:20:11 -05001451 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
1452 passed zero arguments or more than one argument or when passed a
1453 non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001454 passed an incorrect cipher list string.
1455 """
1456 context = Context(TLSv1_METHOD)
1457 self.assertRaises(TypeError, context.set_cipher_list)
1458 self.assertRaises(TypeError, context.set_cipher_list, object())
1459 self.assertRaises(TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object())
1460
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001461 self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001462
1463
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001464 def test_set_session_cache_mode_wrong_args(self):
1465 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001466 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1467 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001468 """
1469 context = Context(TLSv1_METHOD)
1470 self.assertRaises(TypeError, context.set_session_cache_mode)
1471 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1472
1473
1474 def test_get_session_cache_mode_wrong_args(self):
1475 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001476 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1477 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001478 """
1479 context = Context(TLSv1_METHOD)
1480 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1481
1482
1483 def test_session_cache_mode(self):
1484 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001485 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1486 cached. The setting can be retrieved via
1487 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001488 """
1489 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001490 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001491 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1492 self.assertEqual(SESS_CACHE_OFF, off)
1493 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1494
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001495 if not PY3:
1496 def test_session_cache_mode_long(self):
1497 """
1498 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1499 of type :py:obj:`long` as well as :py:obj:`int`.
1500 """
1501 context = Context(TLSv1_METHOD)
1502 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1503 self.assertEqual(
1504 SESS_CACHE_BOTH, context.get_session_cache_mode())
1505
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001506
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001507 def test_get_cert_store(self):
1508 """
1509 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store` instance.
1510 """
1511 context = Context(TLSv1_METHOD)
1512 store = context.get_cert_store()
1513 self.assertIsInstance(store, X509Store)
1514
1515
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001516
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001517class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1518 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001519 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
1520 :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001521 """
1522 def test_wrong_args(self):
1523 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001524 :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001525 with other than one argument.
1526 """
1527 context = Context(TLSv1_METHOD)
1528 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1529 self.assertRaises(
1530 TypeError, context.set_tlsext_servername_callback, 1, 2)
1531
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001532
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001533 def test_old_callback_forgotten(self):
1534 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001535 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001536 callback, the one it replaces is dereferenced.
1537 """
1538 def callback(connection):
1539 pass
1540
1541 def replacement(connection):
1542 pass
1543
1544 context = Context(TLSv1_METHOD)
1545 context.set_tlsext_servername_callback(callback)
1546
1547 tracker = ref(callback)
1548 del callback
1549
1550 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001551
1552 # One run of the garbage collector happens to work on CPython. PyPy
1553 # doesn't collect the underlying object until a second run for whatever
1554 # reason. That's fine, it still demonstrates our code has properly
1555 # dropped the reference.
1556 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001557 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001558
1559 callback = tracker()
1560 if callback is not None:
1561 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001562 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001563 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001564
1565
1566 def test_no_servername(self):
1567 """
1568 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001569 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
1570 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001571 """
1572 args = []
1573 def servername(conn):
1574 args.append((conn, conn.get_servername()))
1575 context = Context(TLSv1_METHOD)
1576 context.set_tlsext_servername_callback(servername)
1577
1578 # Lose our reference to it. The Context is responsible for keeping it
1579 # alive now.
1580 del servername
1581 collect()
1582
1583 # Necessary to actually accept the connection
1584 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1585 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1586
1587 # Do a little connection to trigger the logic
1588 server = Connection(context, None)
1589 server.set_accept_state()
1590
1591 client = Connection(Context(TLSv1_METHOD), None)
1592 client.set_connect_state()
1593
1594 self._interactInMemory(server, client)
1595
1596 self.assertEqual([(server, None)], args)
1597
1598
1599 def test_servername(self):
1600 """
1601 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +09001602 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
1603 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001604 """
1605 args = []
1606 def servername(conn):
1607 args.append((conn, conn.get_servername()))
1608 context = Context(TLSv1_METHOD)
1609 context.set_tlsext_servername_callback(servername)
1610
1611 # Necessary to actually accept the connection
1612 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1613 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1614
1615 # Do a little connection to trigger the logic
1616 server = Connection(context, None)
1617 server.set_accept_state()
1618
1619 client = Connection(Context(TLSv1_METHOD), None)
1620 client.set_connect_state()
1621 client.set_tlsext_host_name(b("foo1.example.com"))
1622
1623 self._interactInMemory(server, client)
1624
1625 self.assertEqual([(server, b("foo1.example.com"))], args)
1626
1627
Cory Benfield84a121e2014-03-31 20:30:25 +01001628class NextProtoNegotiationTests(TestCase, _LoopbackMixin):
1629 """
1630 Test for Next Protocol Negotiation in PyOpenSSL.
1631 """
1632 def test_npn_success(self):
Cory Benfieldbe3e7b82014-05-10 09:48:55 +01001633 """
1634 Tests that clients and servers that agree on the negotiated next
1635 protocol can correct establish a connection, and that the agreed
1636 protocol is reported by the connections.
1637 """
1638 advertise_args = []
Cory Benfield84a121e2014-03-31 20:30:25 +01001639 select_args = []
1640 def advertise(conn):
1641 advertise_args.append((conn,))
Cory Benfieldbe3e7b82014-05-10 09:48:55 +01001642 return [b'http/1.1', b'spdy/2']
Cory Benfield84a121e2014-03-31 20:30:25 +01001643 def select(conn, options):
1644 select_args.append((conn, options))
Cory Benfieldbe3e7b82014-05-10 09:48:55 +01001645 return b'spdy/2'
Cory Benfield84a121e2014-03-31 20:30:25 +01001646
1647 server_context = Context(TLSv1_METHOD)
1648 server_context.set_npn_advertise_callback(advertise)
1649
1650 client_context = Context(TLSv1_METHOD)
1651 client_context.set_npn_select_callback(select)
1652
1653 # Necessary to actually accept the connection
1654 server_context.use_privatekey(
1655 load_privatekey(FILETYPE_PEM, server_key_pem))
1656 server_context.use_certificate(
1657 load_certificate(FILETYPE_PEM, server_cert_pem))
1658
1659 # Do a little connection to trigger the logic
1660 server = Connection(server_context, None)
1661 server.set_accept_state()
1662
1663 client = Connection(client_context, None)
1664 client.set_connect_state()
1665
1666 self._interactInMemory(server, client)
1667
1668 self.assertEqual([(server,)], advertise_args)
Cory Benfieldbe3e7b82014-05-10 09:48:55 +01001669 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001670
Cory Benfieldbe3e7b82014-05-10 09:48:55 +01001671 self.assertEqual(server.get_next_proto_negotiated(), b'spdy/2')
1672 self.assertEqual(client.get_next_proto_negotiated(), b'spdy/2')
Cory Benfield84a121e2014-03-31 20:30:25 +01001673
1674
1675 def test_npn_client_fail(self):
Cory Benfieldbe3e7b82014-05-10 09:48:55 +01001676 """
1677 Tests that when clients and servers cannot agree on what protocol to
1678 use next that the TLS connection does not get established.
1679 """
1680 advertise_args = []
Cory Benfield84a121e2014-03-31 20:30:25 +01001681 select_args = []
1682 def advertise(conn):
1683 advertise_args.append((conn,))
Cory Benfieldbe3e7b82014-05-10 09:48:55 +01001684 return [b'http/1.1', b'spdy/2']
Cory Benfield84a121e2014-03-31 20:30:25 +01001685 def select(conn, options):
1686 select_args.append((conn, options))
Cory Benfieldbe3e7b82014-05-10 09:48:55 +01001687 return b''
Cory Benfield84a121e2014-03-31 20:30:25 +01001688
1689 server_context = Context(TLSv1_METHOD)
1690 server_context.set_npn_advertise_callback(advertise)
1691
1692 client_context = Context(TLSv1_METHOD)
1693 client_context.set_npn_select_callback(select)
1694
1695 # Necessary to actually accept the connection
1696 server_context.use_privatekey(
1697 load_privatekey(FILETYPE_PEM, server_key_pem))
1698 server_context.use_certificate(
1699 load_certificate(FILETYPE_PEM, server_cert_pem))
1700
1701 # Do a little connection to trigger the logic
1702 server = Connection(server_context, None)
1703 server.set_accept_state()
1704
1705 client = Connection(client_context, None)
1706 client.set_connect_state()
1707
1708 # If the client doesn't return anything, the connection will fail.
1709 self.assertRaises(Error, self._interactInMemory, server, client)
1710
1711 self.assertEqual([(server,)], advertise_args)
Cory Benfieldbe3e7b82014-05-10 09:48:55 +01001712 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001713
1714
Cory Benfield0ea76e72015-03-22 09:05:28 +00001715 def test_npn_select_error(self):
1716 """
1717 Test that we can handle exceptions in the select callback. If select
1718 fails it should be fatal to the connection.
1719 """
1720 advertise_args = []
1721 def advertise(conn):
1722 advertise_args.append((conn,))
1723 return [b'http/1.1', b'spdy/2']
1724 def select(conn, options):
1725 raise TypeError
1726
1727 server_context = Context(TLSv1_METHOD)
1728 server_context.set_npn_advertise_callback(advertise)
1729
1730 client_context = Context(TLSv1_METHOD)
1731 client_context.set_npn_select_callback(select)
1732
1733 # Necessary to actually accept the connection
1734 server_context.use_privatekey(
1735 load_privatekey(FILETYPE_PEM, server_key_pem))
1736 server_context.use_certificate(
1737 load_certificate(FILETYPE_PEM, server_cert_pem))
1738
1739 # Do a little connection to trigger the logic
1740 server = Connection(server_context, None)
1741 server.set_accept_state()
1742
1743 client = Connection(client_context, None)
1744 client.set_connect_state()
1745
1746 # If the callback throws an exception it should be raised here.
1747 self.assertRaises(TypeError, self._interactInMemory, server, client)
1748 self.assertEqual([(server,)], advertise_args)
1749
1750
1751 def test_npn_advertise_error(self):
1752 """
1753 Test that we can handle exceptions in the advertise callback. If
1754 advertise fails no NPN is advertised to the client.
1755 """
1756 select_args = []
1757 def advertise(conn):
1758 raise TypeError
1759 def select(conn, options):
1760 select_args.append((conn, options))
1761 return b''
1762
1763 server_context = Context(TLSv1_METHOD)
1764 server_context.set_npn_advertise_callback(advertise)
1765
1766 client_context = Context(TLSv1_METHOD)
1767 client_context.set_npn_select_callback(select)
1768
1769 # Necessary to actually accept the connection
1770 server_context.use_privatekey(
1771 load_privatekey(FILETYPE_PEM, server_key_pem))
1772 server_context.use_certificate(
1773 load_certificate(FILETYPE_PEM, server_cert_pem))
1774
1775 # Do a little connection to trigger the logic
1776 server = Connection(server_context, None)
1777 server.set_accept_state()
1778
1779 client = Connection(client_context, None)
1780 client.set_connect_state()
1781
1782 # If the client doesn't return anything, the connection will fail.
1783 self.assertRaises(TypeError, self._interactInMemory, server, client)
1784 self.assertEqual([], select_args)
1785
1786
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001787
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001788class SessionTests(TestCase):
1789 """
1790 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1791 """
1792 def test_construction(self):
1793 """
1794 :py:class:`Session` can be constructed with no arguments, creating a new
1795 instance of that type.
1796 """
1797 new_session = Session()
1798 self.assertTrue(isinstance(new_session, Session))
1799
1800
1801 def test_construction_wrong_args(self):
1802 """
1803 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
1804 is raised.
1805 """
1806 self.assertRaises(TypeError, Session, 123)
1807 self.assertRaises(TypeError, Session, "hello")
1808 self.assertRaises(TypeError, Session, object())
1809
1810
1811
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001812class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05001813 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001814 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001815 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001816 # XXX get_peer_certificate -> None
1817 # XXX sock_shutdown
1818 # XXX master_key -> TypeError
1819 # XXX server_random -> TypeError
1820 # XXX state_string
1821 # XXX connect -> TypeError
1822 # XXX connect_ex -> TypeError
1823 # XXX set_connect_state -> TypeError
1824 # XXX set_accept_state -> TypeError
1825 # XXX renegotiate_pending
1826 # XXX do_handshake -> TypeError
1827 # XXX bio_read -> TypeError
1828 # XXX recv -> TypeError
1829 # XXX send -> TypeError
1830 # XXX bio_write -> TypeError
1831
Rick Deane15b1472009-07-09 15:53:42 -05001832 def test_type(self):
1833 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001834 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001835 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05001836 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001837 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05001838 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001839 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05001840
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001841
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001842 def test_get_context(self):
1843 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001844 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
1845 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001846 """
1847 context = Context(TLSv1_METHOD)
1848 connection = Connection(context, None)
1849 self.assertIdentical(connection.get_context(), context)
1850
1851
1852 def test_get_context_wrong_args(self):
1853 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001854 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001855 arguments.
1856 """
1857 connection = Connection(Context(TLSv1_METHOD), None)
1858 self.assertRaises(TypeError, connection.get_context, None)
1859
1860
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001861 def test_set_context_wrong_args(self):
1862 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001863 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
1864 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001865 than 1.
1866 """
1867 ctx = Context(TLSv1_METHOD)
1868 connection = Connection(ctx, None)
1869 self.assertRaises(TypeError, connection.set_context)
1870 self.assertRaises(TypeError, connection.set_context, object())
1871 self.assertRaises(TypeError, connection.set_context, "hello")
1872 self.assertRaises(TypeError, connection.set_context, 1)
1873 self.assertRaises(TypeError, connection.set_context, 1, 2)
1874 self.assertRaises(
1875 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
1876 self.assertIdentical(ctx, connection.get_context())
1877
1878
1879 def test_set_context(self):
1880 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001881 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001882 for the connection.
1883 """
1884 original = Context(SSLv23_METHOD)
1885 replacement = Context(TLSv1_METHOD)
1886 connection = Connection(original, None)
1887 connection.set_context(replacement)
1888 self.assertIdentical(replacement, connection.get_context())
1889 # Lose our references to the contexts, just in case the Connection isn't
1890 # properly managing its own contributions to their reference counts.
1891 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001892 collect()
1893
1894
1895 def test_set_tlsext_host_name_wrong_args(self):
1896 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001897 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001898 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09001899 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001900 """
1901 conn = Connection(Context(TLSv1_METHOD), None)
1902 self.assertRaises(TypeError, conn.set_tlsext_host_name)
1903 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
1904 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
1905 self.assertRaises(
1906 TypeError, conn.set_tlsext_host_name, b("with\0null"))
1907
Abraham Martinc5484ba2015-03-25 15:33:05 +00001908 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001909 # On Python 3.x, don't accidentally implicitly convert from text.
1910 self.assertRaises(
1911 TypeError,
1912 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001913
1914
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001915 def test_get_servername_wrong_args(self):
1916 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001917 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001918 arguments.
1919 """
1920 connection = Connection(Context(TLSv1_METHOD), None)
1921 self.assertRaises(TypeError, connection.get_servername, object())
1922 self.assertRaises(TypeError, connection.get_servername, 1)
1923 self.assertRaises(TypeError, connection.get_servername, "hello")
1924
1925
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001926 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001927 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001928 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001929 immediate read.
1930 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001931 connection = Connection(Context(TLSv1_METHOD), None)
1932 self.assertEquals(connection.pending(), 0)
1933
1934
1935 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001936 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001937 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001938 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001939 connection = Connection(Context(TLSv1_METHOD), None)
1940 self.assertRaises(TypeError, connection.pending, None)
1941
1942
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001943 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001944 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001945 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001946 argument or with the wrong number of arguments.
1947 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001948 connection = Connection(Context(TLSv1_METHOD), socket())
1949 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001950 self.assertRaises(TypeError, connection.connect)
1951 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001952
1953
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001954 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001955 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001956 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001957 connect method raises it.
1958 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001959 client = socket()
1960 context = Context(TLSv1_METHOD)
1961 clientSSL = Connection(context, client)
1962 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04001963 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001964
1965
1966 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001967 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001968 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001969 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001970 port = socket()
1971 port.bind(('', 0))
1972 port.listen(3)
1973
1974 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001975 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
1976 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001977
1978
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001979 if platform == "darwin":
1980 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
1981 else:
1982 def test_connect_ex(self):
1983 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001984 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001985 errno instead of raising an exception.
1986 """
1987 port = socket()
1988 port.bind(('', 0))
1989 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001990
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001991 clientSSL = Connection(Context(TLSv1_METHOD), socket())
1992 clientSSL.setblocking(False)
1993 result = clientSSL.connect_ex(port.getsockname())
1994 expected = (EINPROGRESS, EWOULDBLOCK)
1995 self.assertTrue(
1996 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001997
1998
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001999 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002000 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002001 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002002 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002003 connection = Connection(Context(TLSv1_METHOD), socket())
2004 self.assertRaises(TypeError, connection.accept, None)
2005
2006
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002007 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002008 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002009 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
2010 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002011 connection originated from.
2012 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002013 ctx = Context(TLSv1_METHOD)
2014 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2015 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002016 port = socket()
2017 portSSL = Connection(ctx, port)
2018 portSSL.bind(('', 0))
2019 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002020
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002021 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002022
2023 # Calling portSSL.getsockname() here to get the server IP address sounds
2024 # great, but frequently fails on Windows.
2025 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002026
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002027 serverSSL, address = portSSL.accept()
2028
2029 self.assertTrue(isinstance(serverSSL, Connection))
2030 self.assertIdentical(serverSSL.get_context(), ctx)
2031 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002032
2033
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002034 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002035 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002036 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002037 number of arguments or with arguments other than integers.
2038 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002039 connection = Connection(Context(TLSv1_METHOD), None)
2040 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04002041 self.assertRaises(TypeError, connection.get_shutdown, None)
2042 self.assertRaises(TypeError, connection.set_shutdown)
2043 self.assertRaises(TypeError, connection.set_shutdown, None)
2044 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002045
2046
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002047 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002048 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002049 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002050 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002051 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002052 self.assertFalse(server.shutdown())
2053 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002054 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002055 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
2056 client.shutdown()
2057 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
2058 self.assertRaises(ZeroReturnError, server.recv, 1024)
2059 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002060
2061
Paul Aurichc85e0862015-01-08 08:34:33 -08002062 def test_shutdown_closed(self):
2063 """
2064 If the underlying socket is closed, :py:obj:`Connection.shutdown` propagates the
2065 write error from the low level write call.
2066 """
2067 server, client = self._loopback()
2068 server.sock_shutdown(2)
2069 exc = self.assertRaises(SysCallError, server.shutdown)
2070 if platform == "win32":
2071 self.assertEqual(exc.args[0], ESHUTDOWN)
2072 else:
2073 self.assertEqual(exc.args[0], EPIPE)
2074
2075
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002076 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002077 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002078 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002079 process.
2080 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002081 connection = Connection(Context(TLSv1_METHOD), socket())
2082 connection.set_shutdown(RECEIVED_SHUTDOWN)
2083 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2084
2085
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002086 if not PY3:
2087 def test_set_shutdown_long(self):
2088 """
2089 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
2090 of type :py:obj:`long` as well as :py:obj:`int`.
2091 """
2092 connection = Connection(Context(TLSv1_METHOD), socket())
2093 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
2094 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2095
2096
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002097 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002098 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002099 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
2100 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002101 with any arguments.
2102 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002103 conn = Connection(Context(TLSv1_METHOD), None)
2104 self.assertRaises(TypeError, conn.get_app_data, None)
2105 self.assertRaises(TypeError, conn.set_app_data)
2106 self.assertRaises(TypeError, conn.set_app_data, None, None)
2107
2108
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002109 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002110 """
2111 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002112 :py:obj:`Connection.set_app_data` and later retrieved with
2113 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002114 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002115 conn = Connection(Context(TLSv1_METHOD), None)
2116 app_data = object()
2117 conn.set_app_data(app_data)
2118 self.assertIdentical(conn.get_app_data(), app_data)
2119
2120
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002121 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002122 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002123 :py:obj:`Connection.makefile` is not implemented and calling that method raises
2124 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002125 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002126 conn = Connection(Context(TLSv1_METHOD), None)
2127 self.assertRaises(NotImplementedError, conn.makefile)
2128
2129
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002130 def test_get_peer_cert_chain_wrong_args(self):
2131 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002132 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002133 arguments.
2134 """
2135 conn = Connection(Context(TLSv1_METHOD), None)
2136 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
2137 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
2138 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
2139 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
2140
2141
2142 def test_get_peer_cert_chain(self):
2143 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002144 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002145 the connected server returned for the certification verification.
2146 """
2147 chain = _create_certificate_chain()
2148 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2149
2150 serverContext = Context(TLSv1_METHOD)
2151 serverContext.use_privatekey(skey)
2152 serverContext.use_certificate(scert)
2153 serverContext.add_extra_chain_cert(icert)
2154 serverContext.add_extra_chain_cert(cacert)
2155 server = Connection(serverContext, None)
2156 server.set_accept_state()
2157
2158 # Create the client
2159 clientContext = Context(TLSv1_METHOD)
2160 clientContext.set_verify(VERIFY_NONE, verify_cb)
2161 client = Connection(clientContext, None)
2162 client.set_connect_state()
2163
2164 self._interactInMemory(client, server)
2165
2166 chain = client.get_peer_cert_chain()
2167 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002168 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002169 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002170 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002171 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002172 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002173 "Authority Certificate", chain[2].get_subject().CN)
2174
2175
2176 def test_get_peer_cert_chain_none(self):
2177 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002178 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002179 certificate chain.
2180 """
2181 ctx = Context(TLSv1_METHOD)
2182 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2183 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2184 server = Connection(ctx, None)
2185 server.set_accept_state()
2186 client = Connection(Context(TLSv1_METHOD), None)
2187 client.set_connect_state()
2188 self._interactInMemory(client, server)
2189 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002190
2191
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002192 def test_get_session_wrong_args(self):
2193 """
2194 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
2195 with any arguments.
2196 """
2197 ctx = Context(TLSv1_METHOD)
2198 server = Connection(ctx, None)
2199 self.assertRaises(TypeError, server.get_session, 123)
2200 self.assertRaises(TypeError, server.get_session, "hello")
2201 self.assertRaises(TypeError, server.get_session, object())
2202
2203
2204 def test_get_session_unconnected(self):
2205 """
2206 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
2207 an object which has not been connected.
2208 """
2209 ctx = Context(TLSv1_METHOD)
2210 server = Connection(ctx, None)
2211 session = server.get_session()
2212 self.assertIdentical(None, session)
2213
2214
2215 def test_server_get_session(self):
2216 """
2217 On the server side of a connection, :py:obj:`Connection.get_session`
2218 returns a :py:class:`Session` instance representing the SSL session for
2219 that connection.
2220 """
2221 server, client = self._loopback()
2222 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002223 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002224
2225
2226 def test_client_get_session(self):
2227 """
2228 On the client side of a connection, :py:obj:`Connection.get_session`
2229 returns a :py:class:`Session` instance representing the SSL session for
2230 that connection.
2231 """
2232 server, client = self._loopback()
2233 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002234 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002235
2236
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002237 def test_set_session_wrong_args(self):
2238 """
2239 If called with an object that is not an instance of :py:class:`Session`,
2240 or with other than one argument, :py:obj:`Connection.set_session` raises
2241 :py:obj:`TypeError`.
2242 """
2243 ctx = Context(TLSv1_METHOD)
2244 connection = Connection(ctx, None)
2245 self.assertRaises(TypeError, connection.set_session)
2246 self.assertRaises(TypeError, connection.set_session, 123)
2247 self.assertRaises(TypeError, connection.set_session, "hello")
2248 self.assertRaises(TypeError, connection.set_session, object())
2249 self.assertRaises(
2250 TypeError, connection.set_session, Session(), Session())
2251
2252
2253 def test_client_set_session(self):
2254 """
2255 :py:obj:`Connection.set_session`, when used prior to a connection being
2256 established, accepts a :py:class:`Session` instance and causes an
2257 attempt to re-use the session it represents when the SSL handshake is
2258 performed.
2259 """
2260 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2261 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2262 ctx = Context(TLSv1_METHOD)
2263 ctx.use_privatekey(key)
2264 ctx.use_certificate(cert)
2265 ctx.set_session_id("unity-test")
2266
2267 def makeServer(socket):
2268 server = Connection(ctx, socket)
2269 server.set_accept_state()
2270 return server
2271
2272 originalServer, originalClient = self._loopback(
2273 serverFactory=makeServer)
2274 originalSession = originalClient.get_session()
2275
2276 def makeClient(socket):
2277 client = self._loopbackClientFactory(socket)
2278 client.set_session(originalSession)
2279 return client
2280 resumedServer, resumedClient = self._loopback(
2281 serverFactory=makeServer,
2282 clientFactory=makeClient)
2283
2284 # This is a proxy: in general, we have no access to any unique
2285 # identifier for the session (new enough versions of OpenSSL expose a
2286 # hash which could be usable, but "new enough" is very, very new).
2287 # Instead, exploit the fact that the master key is re-used if the
2288 # session is re-used. As long as the master key for the two connections
2289 # is the same, the session was re-used!
2290 self.assertEqual(
2291 originalServer.master_key(), resumedServer.master_key())
2292
2293
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002294 def test_set_session_wrong_method(self):
2295 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002296 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
2297 instance associated with a context using a different SSL method than the
2298 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
2299 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002300 """
2301 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2302 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2303 ctx = Context(TLSv1_METHOD)
2304 ctx.use_privatekey(key)
2305 ctx.use_certificate(cert)
2306 ctx.set_session_id("unity-test")
2307
2308 def makeServer(socket):
2309 server = Connection(ctx, socket)
2310 server.set_accept_state()
2311 return server
2312
2313 originalServer, originalClient = self._loopback(
2314 serverFactory=makeServer)
2315 originalSession = originalClient.get_session()
2316
2317 def makeClient(socket):
2318 # Intentionally use a different, incompatible method here.
2319 client = Connection(Context(SSLv3_METHOD), socket)
2320 client.set_connect_state()
2321 client.set_session(originalSession)
2322 return client
2323
2324 self.assertRaises(
2325 Error,
2326 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2327
2328
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002329 def test_wantWriteError(self):
2330 """
2331 :py:obj:`Connection` methods which generate output raise
2332 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2333 fail indicating a should-write state.
2334 """
2335 client_socket, server_socket = socket_pair()
2336 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002337 # anything. Only write a single byte at a time so we can be sure we
2338 # completely fill the buffer. Even though the socket API is allowed to
2339 # signal a short write via its return value it seems this doesn't
2340 # always happen on all platforms (FreeBSD and OS X particular) for the
2341 # very last bit of available buffer space.
2342 msg = b"x"
2343 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002344 try:
2345 client_socket.send(msg)
2346 except error as e:
2347 if e.errno == EWOULDBLOCK:
2348 break
2349 raise
2350 else:
2351 self.fail(
2352 "Failed to fill socket buffer, cannot test BIO want write")
2353
2354 ctx = Context(TLSv1_METHOD)
2355 conn = Connection(ctx, client_socket)
2356 # Client's speak first, so make it an SSL client
2357 conn.set_connect_state()
2358 self.assertRaises(WantWriteError, conn.do_handshake)
2359
2360 # XXX want_read
2361
Fedor Brunner416f4a12014-03-28 13:18:38 +01002362 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002363 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002364 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2365 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002366 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002367 ctx = Context(TLSv1_METHOD)
2368 connection = Connection(ctx, None)
2369 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002370
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002371
Fedor Brunner416f4a12014-03-28 13:18:38 +01002372 def test_get_peer_finished_before_connect(self):
2373 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002374 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2375 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002376 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002377 ctx = Context(TLSv1_METHOD)
2378 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002379 self.assertEqual(connection.get_peer_finished(), None)
2380
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002381
Fedor Brunner416f4a12014-03-28 13:18:38 +01002382 def test_get_finished(self):
2383 """
2384 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002385 message send from client, or server. Finished messages are send during
2386 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002387 """
2388
Fedor Brunner5747b932014-03-05 14:22:34 +01002389 server, client = self._loopback()
2390
2391 self.assertNotEqual(server.get_finished(), None)
2392 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002393
Jean-Paul Calderoned979f232014-03-30 11:58:00 -04002394
Fedor Brunner416f4a12014-03-28 13:18:38 +01002395 def test_get_peer_finished(self):
2396 """
2397 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002398 message received from client, or server. Finished messages are send
2399 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002400 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002401 server, client = self._loopback()
2402
2403 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002404 self.assertTrue(len(server.get_peer_finished()) > 0)
2405
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002406
Fedor Brunner416f4a12014-03-28 13:18:38 +01002407 def test_tls_finished_message_symmetry(self):
2408 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002409 The TLS Finished message send by server must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002410 received by client.
2411
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002412 The TLS Finished message send by client must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002413 received by server.
2414 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002415 server, client = self._loopback()
2416
Fedor Brunner5747b932014-03-05 14:22:34 +01002417 self.assertEqual(server.get_finished(), client.get_peer_finished())
2418 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002419
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002420
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002421 def test_get_cipher_name_before_connect(self):
2422 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002423 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2424 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002425 """
2426 ctx = Context(TLSv1_METHOD)
2427 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002428 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002429
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002430
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002431 def test_get_cipher_name(self):
2432 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002433 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2434 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002435 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002436 server, client = self._loopback()
2437 server_cipher_name, client_cipher_name = \
2438 server.get_cipher_name(), client.get_cipher_name()
2439
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002440 self.assertIsInstance(server_cipher_name, text_type)
2441 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002442
2443 self.assertEqual(server_cipher_name, client_cipher_name)
2444
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002445
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002446 def test_get_cipher_version_before_connect(self):
2447 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002448 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2449 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002450 """
2451 ctx = Context(TLSv1_METHOD)
2452 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002453 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002454
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002455
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002456 def test_get_cipher_version(self):
2457 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002458 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2459 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002460 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002461 server, client = self._loopback()
2462 server_cipher_version, client_cipher_version = \
2463 server.get_cipher_version(), client.get_cipher_version()
2464
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002465 self.assertIsInstance(server_cipher_version, text_type)
2466 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002467
2468 self.assertEqual(server_cipher_version, client_cipher_version)
2469
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002470
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002471 def test_get_cipher_bits_before_connect(self):
2472 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002473 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2474 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002475 """
2476 ctx = Context(TLSv1_METHOD)
2477 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002478 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002479
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002480
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002481 def test_get_cipher_bits(self):
2482 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002483 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2484 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002485 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002486 server, client = self._loopback()
2487 server_cipher_bits, client_cipher_bits = \
2488 server.get_cipher_bits(), client.get_cipher_bits()
2489
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002490 self.assertIsInstance(server_cipher_bits, int)
2491 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002492
2493 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002494
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002495
2496
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002497class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002498 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002499 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002500 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002501 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002502 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002503 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002504 arguments.
2505 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002506 connection = Connection(Context(TLSv1_METHOD), None)
2507 self.assertRaises(TypeError, connection.get_cipher_list, None)
2508
2509
2510 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002511 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002512 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2513 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002514 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002515 connection = Connection(Context(TLSv1_METHOD), None)
2516 ciphers = connection.get_cipher_list()
2517 self.assertTrue(isinstance(ciphers, list))
2518 for cipher in ciphers:
2519 self.assertTrue(isinstance(cipher, str))
2520
2521
2522
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002523class ConnectionSendTests(TestCase, _LoopbackMixin):
2524 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002525 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002526 """
2527 def test_wrong_args(self):
2528 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002529 When called with arguments other than string argument for its first
2530 parameter or more than two arguments, :py:obj:`Connection.send` raises
2531 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002532 """
2533 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002534 self.assertRaises(TypeError, connection.send)
2535 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002536 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002537
2538
2539 def test_short_bytes(self):
2540 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002541 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002542 and returns the number of bytes sent.
2543 """
2544 server, client = self._loopback()
2545 count = server.send(b('xy'))
2546 self.assertEquals(count, 2)
2547 self.assertEquals(client.recv(2), b('xy'))
2548
Abraham Martinef063482015-03-25 14:06:24 +00002549
2550 def test_text(self):
2551 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002552 When passed a text, :py:obj:`Connection.send` transmits all of it and
2553 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002554 """
2555 server, client = self._loopback()
2556 with catch_warnings(record=True) as w:
2557 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002558 count = server.send(b"xy".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002559 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002560 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002561 WARNING_TYPE_EXPECTED
2562 ),
2563 str(w[-1].message)
2564 )
2565 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinef063482015-03-25 14:06:24 +00002566 self.assertEquals(count, 2)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002567 self.assertEquals(client.recv(2), b"xy")
Abraham Martinef063482015-03-25 14:06:24 +00002568
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002569 try:
2570 memoryview
2571 except NameError:
2572 "cannot test sending memoryview without memoryview"
2573 else:
2574 def test_short_memoryview(self):
2575 """
2576 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002577 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002578 bytes sent.
2579 """
2580 server, client = self._loopback()
2581 count = server.send(memoryview(b('xy')))
2582 self.assertEquals(count, 2)
2583 self.assertEquals(client.recv(2), b('xy'))
2584
2585
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002586 try:
2587 buffer
2588 except NameError:
2589 "cannot test sending buffer without buffer"
2590 else:
2591 def test_short_buffer(self):
2592 """
2593 When passed a buffer containing a small number of bytes,
2594 :py:obj:`Connection.send` transmits all of them and returns the number of
2595 bytes sent.
2596 """
2597 server, client = self._loopback()
2598 count = server.send(buffer(b('xy')))
2599 self.assertEquals(count, 2)
2600 self.assertEquals(client.recv(2), b('xy'))
2601
2602
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002603
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002604def _make_memoryview(size):
2605 """
2606 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2607 size.
2608 """
2609 return memoryview(bytearray(size))
2610
2611
2612
Cory Benfield62d10332014-06-15 10:03:41 +01002613class ConnectionRecvIntoTests(TestCase, _LoopbackMixin):
2614 """
2615 Tests for :py:obj:`Connection.recv_into`
2616 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002617 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002618 """
2619 Assert that when the given buffer is passed to
2620 ``Connection.recv_into``, whatever bytes are available to be received
2621 that fit into that buffer are written into that buffer.
2622 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002623 output_buffer = factory(5)
2624
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002625 server, client = self._loopback()
2626 server.send(b('xy'))
2627
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002628 self.assertEqual(client.recv_into(output_buffer), 2)
2629 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002630
2631
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002632 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002633 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002634 :py:obj:`Connection.recv_into` can be passed a ``bytearray`` instance
2635 and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002636 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002637 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002638
2639
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002640 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002641 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002642 Assert that when the given buffer is passed to ``Connection.recv_into``
2643 along with a value for ``nbytes`` that is less than the size of that
2644 buffer, only ``nbytes`` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002645 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002646 output_buffer = factory(10)
2647
Cory Benfield62d10332014-06-15 10:03:41 +01002648 server, client = self._loopback()
2649 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002650
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002651 self.assertEqual(client.recv_into(output_buffer, 5), 5)
2652 self.assertEqual(
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002653 output_buffer, bytearray(b('abcde\x00\x00\x00\x00\x00'))
2654 )
2655
2656
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002657 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002658 """
2659 When called with a ``bytearray`` instance,
2660 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter and
2661 doesn't copy in more than that number of bytes.
2662 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002663 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002664
2665
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002666 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002667 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002668 Assert that if there are more bytes available to be read from the
2669 receive buffer than would fit into the buffer passed to
2670 :py:obj:`Connection.recv_into`, only as many as fit are written into
2671 it.
Cory Benfield62d10332014-06-15 10:03:41 +01002672 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002673 output_buffer = factory(5)
2674
Cory Benfield62d10332014-06-15 10:03:41 +01002675 server, client = self._loopback()
2676 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002677
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002678 self.assertEqual(client.recv_into(output_buffer), 5)
2679 self.assertEqual(output_buffer, bytearray(b('abcde')))
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002680 rest = client.recv(5)
2681 self.assertEqual(b('fghij'), rest)
2682
2683
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002684 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002685 """
2686 When called with a ``bytearray`` instance,
2687 :py:obj:`Connection.recv_into` respects the size of the array and
2688 doesn't write more bytes into it than will fit.
2689 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002690 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002691
2692
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002693 def _really_doesnt_overfill_test(self, factory):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002694 """
2695 Assert that if the value given by ``nbytes`` is greater than the actual
2696 size of the output buffer passed to :py:obj:`Connection.recv_into`, the
2697 behavior is as if no value was given for ``nbytes`` at all.
2698 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002699 output_buffer = factory(5)
2700
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002701 server, client = self._loopback()
2702 server.send(b('abcdefghij'))
2703
2704 self.assertEqual(client.recv_into(output_buffer, 50), 5)
2705 self.assertEqual(output_buffer, bytearray(b('abcde')))
2706 rest = client.recv(5)
2707 self.assertEqual(b('fghij'), rest)
2708
2709
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002710 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002711 """
2712 When called with a ``bytearray`` instance and an ``nbytes`` value that
2713 is too large, :py:obj:`Connection.recv_into` respects the size of the
2714 array and not the ``nbytes`` value and doesn't write more bytes into
2715 the buffer than will fit.
2716 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002717 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002718
2719
Cory Benfield62d10332014-06-15 10:03:41 +01002720 try:
2721 memoryview
2722 except NameError:
2723 "cannot test recv_into memoryview without memoryview"
2724 else:
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002725 def test_memoryview_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002726 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002727 :py:obj:`Connection.recv_into` can be passed a ``memoryview``
2728 instance and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002729 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002730 self._no_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002731
2732
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002733 def test_memoryview_respects_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002734 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002735 When called with a ``memoryview`` instance,
2736 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter
2737 and doesn't copy more than that number of bytes in.
Cory Benfield62d10332014-06-15 10:03:41 +01002738 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002739 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002740
2741
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002742 def test_memoryview_doesnt_overfill(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002743 """
Jean-Paul Calderone8fd82552015-03-15 17:21:07 -04002744 When called with a ``memoryview`` instance,
2745 :py:obj:`Connection.recv_into` respects the size of the array and
2746 doesn't write more bytes into it than will fit.
Cory Benfield62d10332014-06-15 10:03:41 +01002747 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002748 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002749
2750
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002751 def test_memoryview_really_doesnt_overfill(self):
2752 """
2753 When called with a ``memoryview`` instance and an ``nbytes`` value
2754 that is too large, :py:obj:`Connection.recv_into` respects the size
2755 of the array and not the ``nbytes`` value and doesn't write more
2756 bytes into the buffer than will fit.
2757 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002758 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002759
2760
Cory Benfield62d10332014-06-15 10:03:41 +01002761
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002762class ConnectionSendallTests(TestCase, _LoopbackMixin):
2763 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002764 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002765 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002766 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002767 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002768 When called with arguments other than a string argument for its first
2769 parameter or with more than two arguments, :py:obj:`Connection.sendall`
2770 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002771 """
2772 connection = Connection(Context(TLSv1_METHOD), None)
2773 self.assertRaises(TypeError, connection.sendall)
2774 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002775 self.assertRaises(
2776 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002777
2778
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002779 def test_short(self):
2780 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002781 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002782 it.
2783 """
2784 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04002785 server.sendall(b('x'))
2786 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002787
2788
Abraham Martinef063482015-03-25 14:06:24 +00002789 def test_text(self):
2790 """
2791 :py:obj:`Connection.sendall` transmits all the content in the string passed to
2792 it raising a DepreactionWarning in case of this being a text.
2793 """
2794 server, client = self._loopback()
2795 with catch_warnings(record=True) as w:
2796 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04002797 server.sendall(b"x".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002798 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002799 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002800 WARNING_TYPE_EXPECTED
2801 ),
2802 str(w[-1].message)
2803 )
2804 self.assertIs(w[-1].category, DeprecationWarning)
2805 self.assertEquals(client.recv(1), b"x")
Abraham Martinef063482015-03-25 14:06:24 +00002806
2807
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002808 try:
2809 memoryview
2810 except NameError:
2811 "cannot test sending memoryview without memoryview"
2812 else:
2813 def test_short_memoryview(self):
2814 """
2815 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002816 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002817 """
2818 server, client = self._loopback()
2819 server.sendall(memoryview(b('x')))
2820 self.assertEquals(client.recv(1), b('x'))
2821
2822
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002823 try:
2824 buffer
2825 except NameError:
2826 "cannot test sending buffers without buffers"
2827 else:
2828 def test_short_buffers(self):
2829 """
2830 When passed a buffer containing a small number of bytes,
2831 :py:obj:`Connection.sendall` transmits all of them.
2832 """
2833 server, client = self._loopback()
2834 server.sendall(buffer(b('x')))
2835 self.assertEquals(client.recv(1), b('x'))
2836
2837
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002838 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002839 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002840 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002841 it even if this requires multiple calls of an underlying write function.
2842 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002843 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04002844 # Should be enough, underlying SSL_write should only do 16k at a time.
2845 # On Windows, after 32k of bytes the write will block (forever - because
2846 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04002847 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002848 server.sendall(message)
2849 accum = []
2850 received = 0
2851 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04002852 data = client.recv(1024)
2853 accum.append(data)
2854 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04002855 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002856
2857
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002858 def test_closed(self):
2859 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002860 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002861 write error from the low level write call.
2862 """
2863 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04002864 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002865 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02002866 if platform == "win32":
2867 self.assertEqual(exc.args[0], ESHUTDOWN)
2868 else:
2869 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002870
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002871
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002872
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002873class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
2874 """
2875 Tests for SSL renegotiation APIs.
2876 """
2877 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002878 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002879 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002880 arguments.
2881 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002882 connection = Connection(Context(TLSv1_METHOD), None)
2883 self.assertRaises(TypeError, connection.renegotiate, None)
2884
2885
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002886 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002887 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002888 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002889 any arguments.
2890 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002891 connection = Connection(Context(TLSv1_METHOD), None)
2892 self.assertRaises(TypeError, connection.total_renegotiations, None)
2893
2894
2895 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002896 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002897 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002898 renegotiations have happened.
2899 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002900 connection = Connection(Context(TLSv1_METHOD), None)
2901 self.assertEquals(connection.total_renegotiations(), 0)
2902
2903
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002904# def test_renegotiate(self):
2905# """
2906# """
2907# server, client = self._loopback()
2908
2909# server.send("hello world")
2910# self.assertEquals(client.recv(len("hello world")), "hello world")
2911
2912# self.assertEquals(server.total_renegotiations(), 0)
2913# self.assertTrue(server.renegotiate())
2914
2915# server.setblocking(False)
2916# client.setblocking(False)
2917# while server.renegotiate_pending():
2918# client.do_handshake()
2919# server.do_handshake()
2920
2921# self.assertEquals(server.total_renegotiations(), 1)
2922
2923
2924
2925
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002926class ErrorTests(TestCase):
2927 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002928 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002929 """
2930 def test_type(self):
2931 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002932 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002933 """
2934 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05002935 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05002936
2937
2938
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002939class ConstantsTests(TestCase):
2940 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002941 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002942
2943 These are values defined by OpenSSL intended only to be used as flags to
2944 OpenSSL APIs. The only assertions it seems can be made about them is
2945 their values.
2946 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002947 # unittest.TestCase has no skip mechanism
2948 if OP_NO_QUERY_MTU is not None:
2949 def test_op_no_query_mtu(self):
2950 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002951 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002952 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002953 """
2954 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
2955 else:
2956 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002957
2958
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002959 if OP_COOKIE_EXCHANGE is not None:
2960 def test_op_cookie_exchange(self):
2961 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002962 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002963 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002964 """
2965 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
2966 else:
2967 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002968
2969
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002970 if OP_NO_TICKET is not None:
2971 def test_op_no_ticket(self):
2972 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002973 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002974 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002975 """
2976 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04002977 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002978 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05002979
2980
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002981 if OP_NO_COMPRESSION is not None:
2982 def test_op_no_compression(self):
2983 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002984 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
2985 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002986 """
2987 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
2988 else:
2989 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
2990
2991
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002992 def test_sess_cache_off(self):
2993 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002994 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
2995 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002996 """
2997 self.assertEqual(0x0, SESS_CACHE_OFF)
2998
2999
3000 def test_sess_cache_client(self):
3001 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003002 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3003 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003004 """
3005 self.assertEqual(0x1, SESS_CACHE_CLIENT)
3006
3007
3008 def test_sess_cache_server(self):
3009 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003010 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3011 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003012 """
3013 self.assertEqual(0x2, SESS_CACHE_SERVER)
3014
3015
3016 def test_sess_cache_both(self):
3017 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003018 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3019 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003020 """
3021 self.assertEqual(0x3, SESS_CACHE_BOTH)
3022
3023
3024 def test_sess_cache_no_auto_clear(self):
3025 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003026 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3027 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3028 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003029 """
3030 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
3031
3032
3033 def test_sess_cache_no_internal_lookup(self):
3034 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003035 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3036 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3037 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003038 """
3039 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
3040
3041
3042 def test_sess_cache_no_internal_store(self):
3043 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003044 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3045 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3046 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003047 """
3048 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
3049
3050
3051 def test_sess_cache_no_internal(self):
3052 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003053 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3054 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
3055 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003056 """
3057 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
3058
3059
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04003060
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003061class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05003062 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003063 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003064 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003065 def _server(self, sock):
3066 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003067 Create a new server-side SSL :py:obj:`Connection` object wrapped around
3068 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003069 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003070 # Create the server side Connection. This is mostly setup boilerplate
3071 # - use TLSv1, use a particular certificate, etc.
3072 server_ctx = Context(TLSv1_METHOD)
3073 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
3074 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
3075 server_store = server_ctx.get_cert_store()
3076 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3077 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3078 server_ctx.check_privatekey()
3079 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003080 # Here the Connection is actually created. If None is passed as the 2nd
3081 # parameter, it indicates a memory BIO should be created.
3082 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003083 server_conn.set_accept_state()
3084 return server_conn
3085
3086
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003087 def _client(self, sock):
3088 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003089 Create a new client-side SSL :py:obj:`Connection` object wrapped around
3090 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003091 """
3092 # Now create the client side Connection. Similar boilerplate to the
3093 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003094 client_ctx = Context(TLSv1_METHOD)
3095 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
3096 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
3097 client_store = client_ctx.get_cert_store()
3098 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
3099 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
3100 client_ctx.check_privatekey()
3101 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003102 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003103 client_conn.set_connect_state()
3104 return client_conn
3105
3106
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003107 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003108 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003109 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003110 reading from the output of each and writing those bytes to the input of
3111 the other and in this way establish a connection and exchange
3112 application-level bytes with each other.
3113 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003114 server_conn = self._server(None)
3115 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003116
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003117 # There should be no key or nonces yet.
3118 self.assertIdentical(server_conn.master_key(), None)
3119 self.assertIdentical(server_conn.client_random(), None)
3120 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003121
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003122 # First, the handshake needs to happen. We'll deliver bytes back and
3123 # forth between the client and server until neither of them feels like
3124 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003125 self.assertIdentical(
3126 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003127
3128 # Now that the handshake is done, there should be a key and nonces.
3129 self.assertNotIdentical(server_conn.master_key(), None)
3130 self.assertNotIdentical(server_conn.client_random(), None)
3131 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04003132 self.assertEquals(server_conn.client_random(), client_conn.client_random())
3133 self.assertEquals(server_conn.server_random(), client_conn.server_random())
3134 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
3135 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003136
3137 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003138 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05003139
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003140 server_conn.write(important_message)
3141 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003142 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003143 (client_conn, important_message))
3144
3145 client_conn.write(important_message[::-1])
3146 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003147 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003148 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003149
3150
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003151 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003152 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003153 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003154
3155 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09003156 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003157 this test fails, there must be a problem outside the memory BIO
3158 code, as no memory BIO is involved here). Even though this isn't a
3159 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003160 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04003161 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003162
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003163 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05003164 client_conn.send(important_message)
3165 msg = server_conn.recv(1024)
3166 self.assertEqual(msg, important_message)
3167
3168 # Again in the other direction, just for fun.
3169 important_message = important_message[::-1]
3170 server_conn.send(important_message)
3171 msg = client_conn.recv(1024)
3172 self.assertEqual(msg, important_message)
3173
3174
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04003175 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003176 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003177 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
3178 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003179 """
3180 context = Context(SSLv3_METHOD)
3181 client = socket()
3182 clientSSL = Connection(context, client)
3183 self.assertRaises( TypeError, clientSSL.bio_read, 100)
3184 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04003185 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003186
3187
3188 def test_outgoingOverflow(self):
3189 """
3190 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09003191 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003192 returned and that many bytes from the beginning of the input can be
3193 read from the other end of the connection.
3194 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003195 server = self._server(None)
3196 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003197
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003198 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003199
3200 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003201 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003202 # Sanity check. We're trying to test what happens when the entire
3203 # input can't be sent. If the entire input was sent, this test is
3204 # meaningless.
3205 self.assertTrue(sent < size)
3206
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003207 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003208 self.assertIdentical(receiver, server)
3209
3210 # We can rely on all of these bytes being received at once because
3211 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
3212 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003213
3214
3215 def test_shutdown(self):
3216 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003217 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
3218 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003219 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003220 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003221 server.bio_shutdown()
3222 e = self.assertRaises(Error, server.recv, 1024)
3223 # We don't want WantReadError or ZeroReturnError or anything - it's a
3224 # handshake failure.
3225 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003226
3227
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003228 def test_unexpectedEndOfFile(self):
3229 """
3230 If the connection is lost before an orderly SSL shutdown occurs,
3231 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
3232 "Unexpected EOF".
3233 """
3234 server_conn, client_conn = self._loopback()
3235 client_conn.sock_shutdown(SHUT_RDWR)
3236 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
3237 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
3238
3239
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003240 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003241 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003242 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 -04003243
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003244 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003245 before the client and server are connected to each other. This
3246 function should specify a list of CAs for the server to send to the
3247 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09003248 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003249 times.
3250 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003251 server = self._server(None)
3252 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003253 self.assertEqual(client.get_client_ca_list(), [])
3254 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003255 ctx = server.get_context()
3256 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003257 self.assertEqual(client.get_client_ca_list(), [])
3258 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003259 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003260 self.assertEqual(client.get_client_ca_list(), expected)
3261 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003262
3263
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003264 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003265 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003266 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003267 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003268 """
3269 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003270 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
3271 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
3272 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003273
3274
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003275 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003276 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003277 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003278 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09003279 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003280 after the connection is set up.
3281 """
3282 def no_ca(ctx):
3283 ctx.set_client_ca_list([])
3284 return []
3285 self._check_client_ca_list(no_ca)
3286
3287
3288 def test_set_one_ca_list(self):
3289 """
3290 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003291 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003292 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003293 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003294 X509Name after the connection is set up.
3295 """
3296 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3297 cadesc = cacert.get_subject()
3298 def single_ca(ctx):
3299 ctx.set_client_ca_list([cadesc])
3300 return [cadesc]
3301 self._check_client_ca_list(single_ca)
3302
3303
3304 def test_set_multiple_ca_list(self):
3305 """
3306 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003307 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003308 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003309 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003310 X509Names after the connection is set up.
3311 """
3312 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3313 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3314
3315 sedesc = secert.get_subject()
3316 cldesc = clcert.get_subject()
3317
3318 def multiple_ca(ctx):
3319 L = [sedesc, cldesc]
3320 ctx.set_client_ca_list(L)
3321 return L
3322 self._check_client_ca_list(multiple_ca)
3323
3324
3325 def test_reset_ca_list(self):
3326 """
3327 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09003328 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003329 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003330 """
3331 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3332 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3333 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3334
3335 cadesc = cacert.get_subject()
3336 sedesc = secert.get_subject()
3337 cldesc = clcert.get_subject()
3338
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003339 def changed_ca(ctx):
3340 ctx.set_client_ca_list([sedesc, cldesc])
3341 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003342 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003343 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003344
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003345
3346 def test_mutated_ca_list(self):
3347 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003348 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003349 afterwards, this does not affect the list of CA names sent to the
3350 client.
3351 """
3352 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3353 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3354
3355 cadesc = cacert.get_subject()
3356 sedesc = secert.get_subject()
3357
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003358 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003359 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003360 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003361 L.append(sedesc)
3362 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003363 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003364
3365
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003366 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003367 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003368 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003369 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003370 """
3371 ctx = Context(TLSv1_METHOD)
3372 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003373 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003374 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003375 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003376
3377
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003378 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003379 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003380 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09003381 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003382 """
3383 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3384 cadesc = cacert.get_subject()
3385 def single_ca(ctx):
3386 ctx.add_client_ca(cacert)
3387 return [cadesc]
3388 self._check_client_ca_list(single_ca)
3389
3390
3391 def test_multiple_add_client_ca(self):
3392 """
3393 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09003394 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003395 """
3396 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3397 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3398
3399 cadesc = cacert.get_subject()
3400 sedesc = secert.get_subject()
3401
3402 def multiple_ca(ctx):
3403 ctx.add_client_ca(cacert)
3404 ctx.add_client_ca(secert)
3405 return [cadesc, sedesc]
3406 self._check_client_ca_list(multiple_ca)
3407
3408
3409 def test_set_and_add_client_ca(self):
3410 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003411 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
3412 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003413 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003414 """
3415 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3416 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3417 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3418
3419 cadesc = cacert.get_subject()
3420 sedesc = secert.get_subject()
3421 cldesc = clcert.get_subject()
3422
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003423 def mixed_set_add_ca(ctx):
3424 ctx.set_client_ca_list([cadesc, sedesc])
3425 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003426 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003427 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003428
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003429
3430 def test_set_after_add_client_ca(self):
3431 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003432 A call to :py:obj:`Context.set_client_ca_list` after a call to
3433 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003434 call with the names specified by the latter cal.
3435 """
3436 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3437 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3438 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3439
3440 cadesc = cacert.get_subject()
3441 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003442
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003443 def set_replaces_add_ca(ctx):
3444 ctx.add_client_ca(clcert)
3445 ctx.set_client_ca_list([cadesc])
3446 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003447 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003448 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003449
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003450
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003451
3452class ConnectionBIOTests(TestCase):
3453 """
3454 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3455 """
3456 def test_wantReadError(self):
3457 """
3458 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
3459 if there are no bytes available to be read from the BIO.
3460 """
3461 ctx = Context(TLSv1_METHOD)
3462 conn = Connection(ctx, None)
3463 self.assertRaises(WantReadError, conn.bio_read, 1024)
3464
3465
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003466 def test_buffer_size(self):
3467 """
3468 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3469 number of bytes to read and return.
3470 """
3471 ctx = Context(TLSv1_METHOD)
3472 conn = Connection(ctx, None)
3473 conn.set_connect_state()
3474 try:
3475 conn.do_handshake()
3476 except WantReadError:
3477 pass
3478 data = conn.bio_read(2)
3479 self.assertEqual(2, len(data))
3480
3481
3482 if not PY3:
3483 def test_buffer_size_long(self):
3484 """
3485 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3486 :py:obj:`long` as well as :py:obj:`int`.
3487 """
3488 ctx = Context(TLSv1_METHOD)
3489 conn = Connection(ctx, None)
3490 conn.set_connect_state()
3491 try:
3492 conn.do_handshake()
3493 except WantReadError:
3494 pass
3495 data = conn.bio_read(long(2))
3496 self.assertEqual(2, len(data))
3497
3498
3499
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003500
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003501class InfoConstantTests(TestCase):
3502 """
3503 Tests for assorted constants exposed for use in info callbacks.
3504 """
3505 def test_integers(self):
3506 """
3507 All of the info constants are integers.
3508
3509 This is a very weak test. It would be nice to have one that actually
3510 verifies that as certain info events happen, the value passed to the
3511 info callback matches up with the constant exposed by OpenSSL.SSL.
3512 """
3513 for const in [
3514 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3515 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3516 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3517 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3518 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
3519 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
3520
3521 self.assertTrue(isinstance(const, int))
3522
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003523
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003524if __name__ == '__main__':
3525 main()