blob: 16bbf39cdea60f01a68f23e3d37444f53a4b6fb7 [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
Abraham Martinc5484ba2015-03-25 15:33:05 +000012from sys import platform
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 Calderoneb41d1f42014-04-17 16:02:04 -040028from OpenSSL.SSL import _lib
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040029from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
30from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040031from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040032from OpenSSL.SSL import (
33 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
34 TLSv1_1_METHOD, TLSv1_2_METHOD)
35from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040036from OpenSSL.SSL import (
37 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040038
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040039from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050040 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
41 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
42 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
43
44from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070045 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050046from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070047 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040048
Jean-Paul Calderone6462b072015-03-29 07:03:11 -040049from OpenSSL.test.util import WARNING_TYPE_EXPECTED, TestCase, b
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040050from OpenSSL.test.test_crypto import (
51 cleartextCertificatePEM, cleartextPrivateKeyPEM)
52from OpenSSL.test.test_crypto import (
53 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
54 root_cert_pem)
55
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050056try:
57 from OpenSSL.SSL import OP_NO_QUERY_MTU
58except ImportError:
59 OP_NO_QUERY_MTU = None
60try:
61 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
62except ImportError:
63 OP_COOKIE_EXCHANGE = None
64try:
65 from OpenSSL.SSL import OP_NO_TICKET
66except ImportError:
67 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040068
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040069try:
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -040070 from OpenSSL.SSL import OP_NO_COMPRESSION
71except ImportError:
72 OP_NO_COMPRESSION = None
73
74try:
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040075 from OpenSSL.SSL import MODE_RELEASE_BUFFERS
76except ImportError:
77 MODE_RELEASE_BUFFERS = None
78
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040079try:
80 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
81except ImportError:
82 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
83
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040084from OpenSSL.SSL import (
85 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
86 SSL_ST_OK, SSL_ST_RENEGOTIATE,
87 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
88 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
89 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
90 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040091
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040092# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
93# to use)
94dhparam = """\
95-----BEGIN DH PARAMETERS-----
96MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
97-----END DH PARAMETERS-----
98"""
99
100
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400101def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400102 return ok
103
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400104
Rick Deanb1ccd562009-07-09 23:52:39 -0500105def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400106 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400107 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400108 """
109 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500110 port = socket()
111 port.bind(('', 0))
112 port.listen(1)
113 client = socket()
114 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400115 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400116 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500117 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500118
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400119 # Let's pass some unencrypted data to make sure our socket connection is
120 # fine. Just one byte, so we don't have to worry about buffers getting
121 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400122 server.send(b("x"))
123 assert client.recv(1024) == b("x")
124 client.send(b("y"))
125 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500126
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400127 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400128 server.setblocking(False)
129 client.setblocking(False)
130
Rick Deanb1ccd562009-07-09 23:52:39 -0500131 return (server, client)
132
133
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400134
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400135def handshake(client, server):
136 conns = [client, server]
137 while conns:
138 for conn in conns:
139 try:
140 conn.do_handshake()
141 except WantReadError:
142 pass
143 else:
144 conns.remove(conn)
145
146
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400147def _create_certificate_chain():
148 """
149 Construct and return a chain of certificates.
150
151 1. A new self-signed certificate authority certificate (cacert)
152 2. A new intermediate certificate signed by cacert (icert)
153 3. A new server certificate signed by icert (scert)
154 """
155 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
156
157 # Step 1
158 cakey = PKey()
159 cakey.generate_key(TYPE_RSA, 512)
160 cacert = X509()
161 cacert.get_subject().commonName = "Authority Certificate"
162 cacert.set_issuer(cacert.get_subject())
163 cacert.set_pubkey(cakey)
164 cacert.set_notBefore(b("20000101000000Z"))
165 cacert.set_notAfter(b("20200101000000Z"))
166 cacert.add_extensions([caext])
167 cacert.set_serial_number(0)
168 cacert.sign(cakey, "sha1")
169
170 # Step 2
171 ikey = PKey()
172 ikey.generate_key(TYPE_RSA, 512)
173 icert = X509()
174 icert.get_subject().commonName = "Intermediate Certificate"
175 icert.set_issuer(cacert.get_subject())
176 icert.set_pubkey(ikey)
177 icert.set_notBefore(b("20000101000000Z"))
178 icert.set_notAfter(b("20200101000000Z"))
179 icert.add_extensions([caext])
180 icert.set_serial_number(0)
181 icert.sign(cakey, "sha1")
182
183 # Step 3
184 skey = PKey()
185 skey.generate_key(TYPE_RSA, 512)
186 scert = X509()
187 scert.get_subject().commonName = "Server Certificate"
188 scert.set_issuer(icert.get_subject())
189 scert.set_pubkey(skey)
190 scert.set_notBefore(b("20000101000000Z"))
191 scert.set_notAfter(b("20200101000000Z"))
192 scert.add_extensions([
193 X509Extension(b('basicConstraints'), True, b('CA:false'))])
194 scert.set_serial_number(0)
195 scert.sign(ikey, "sha1")
196
197 return [(cakey, cacert), (ikey, icert), (skey, scert)]
198
199
200
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400201class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400202 """
203 Helper mixin which defines methods for creating a connected socket pair and
204 for forcing two connected SSL sockets to talk to each other via memory BIOs.
205 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500206 def _loopbackClientFactory(self, socket):
207 client = Connection(Context(TLSv1_METHOD), socket)
208 client.set_connect_state()
209 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400210
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500211
212 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400213 ctx = Context(TLSv1_METHOD)
214 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
215 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500216 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400217 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500218 return server
219
220
221 def _loopback(self, serverFactory=None, clientFactory=None):
222 if serverFactory is None:
223 serverFactory = self._loopbackServerFactory
224 if clientFactory is None:
225 clientFactory = self._loopbackClientFactory
226
227 (server, client) = socket_pair()
228 server = serverFactory(server)
229 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400230
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400231 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400232
233 server.setblocking(True)
234 client.setblocking(True)
235 return server, client
236
237
238 def _interactInMemory(self, client_conn, server_conn):
239 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900240 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400241 objects. Copy bytes back and forth between their send/receive buffers
242 for as long as there is anything to copy. When there is nothing more
Jonathan Ballet648875f2011-07-16 14:14:58 +0900243 to copy, return :py:obj:`None`. If one of them actually manages to deliver
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400244 some application bytes, return a two-tuple of the connection from which
245 the bytes were read and the bytes themselves.
246 """
247 wrote = True
248 while wrote:
249 # Loop until neither side has anything to say
250 wrote = False
251
252 # Copy stuff from each side's send buffer to the other side's
253 # receive buffer.
254 for (read, write) in [(client_conn, server_conn),
255 (server_conn, client_conn)]:
256
257 # Give the side a chance to generate some more bytes, or
258 # succeed.
259 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400260 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400261 except WantReadError:
262 # It didn't succeed, so we'll hope it generated some
263 # output.
264 pass
265 else:
266 # It did succeed, so we'll stop now and let the caller deal
267 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400268 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400269
270 while True:
271 # Keep copying as long as there's more stuff there.
272 try:
273 dirty = read.bio_read(4096)
274 except WantReadError:
275 # Okay, nothing more waiting to be sent. Stop
276 # processing this send buffer.
277 break
278 else:
279 # Keep track of the fact that someone generated some
280 # output.
281 wrote = True
282 write.bio_write(dirty)
283
284
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400285 def _handshakeInMemory(self, client_conn, server_conn):
Jean-Paul Calderoneb2b40782014-05-06 08:47:40 -0400286 """
287 Perform the TLS handshake between two :py:class:`Connection` instances
288 connected to each other via memory BIOs.
289 """
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400290 client_conn.set_connect_state()
291 server_conn.set_accept_state()
292
293 for conn in [client_conn, server_conn]:
294 try:
295 conn.do_handshake()
296 except WantReadError:
297 pass
298
299 self._interactInMemory(client_conn, server_conn)
300
301
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400302
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400303class VersionTests(TestCase):
304 """
305 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900306 :py:obj:`OpenSSL.SSL.SSLeay_version` and
307 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400308 """
309 def test_OPENSSL_VERSION_NUMBER(self):
310 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900311 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400312 byte and the patch, fix, minor, and major versions in the
313 nibbles above that.
314 """
315 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
316
317
318 def test_SSLeay_version(self):
319 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900320 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400321 one of a number of version strings based on that indicator.
322 """
323 versions = {}
324 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
325 SSLEAY_PLATFORM, SSLEAY_DIR]:
326 version = SSLeay_version(t)
327 versions[version] = t
328 self.assertTrue(isinstance(version, bytes))
329 self.assertEqual(len(versions), 5)
330
331
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400332
333class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400334 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900335 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400336 """
337 def test_method(self):
338 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900339 :py:obj:`Context` can be instantiated with one of :py:obj:`SSLv2_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400340 :py:obj:`SSLv3_METHOD`, :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
341 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400342 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400343 methods = [
344 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
345 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400346 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400347
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400348
349 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
350 for meth in maybe:
351 try:
352 Context(meth)
353 except (Error, ValueError):
354 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
355 # don't. Difficult to say in advance.
356 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400357
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400358 self.assertRaises(TypeError, Context, "")
359 self.assertRaises(ValueError, Context, 10)
360
361
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500362 if not PY3:
363 def test_method_long(self):
364 """
365 On Python 2 :py:class:`Context` accepts values of type
366 :py:obj:`long` as well as :py:obj:`int`.
367 """
368 Context(long(TLSv1_METHOD))
369
370
371
Rick Deane15b1472009-07-09 15:53:42 -0500372 def test_type(self):
373 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900374 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400375 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500376 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400377 self.assertIdentical(Context, ContextType)
378 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500379
380
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400381 def test_use_privatekey(self):
382 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900383 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400384 """
385 key = PKey()
386 key.generate_key(TYPE_RSA, 128)
387 ctx = Context(TLSv1_METHOD)
388 ctx.use_privatekey(key)
389 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400390
391
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800392 def test_use_privatekey_file_missing(self):
393 """
394 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error`
395 when passed the name of a file which does not exist.
396 """
397 ctx = Context(TLSv1_METHOD)
398 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
399
400
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500401 if not PY3:
402 def test_use_privatekey_file_long(self):
403 """
404 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
405 filetype of type :py:obj:`long` as well as :py:obj:`int`.
406 """
407 pemfile = self.mktemp()
408
409 key = PKey()
410 key.generate_key(TYPE_RSA, 128)
411
412 with open(pemfile, "wt") as pem:
413 pem.write(
414 dump_privatekey(FILETYPE_PEM, key).decode("ascii"))
415
416 ctx = Context(TLSv1_METHOD)
417 ctx.use_privatekey_file(pemfile, long(FILETYPE_PEM))
418
419
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800420 def test_use_certificate_wrong_args(self):
421 """
422 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
423 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as an
424 argument.
425 """
426 ctx = Context(TLSv1_METHOD)
427 self.assertRaises(TypeError, ctx.use_certificate)
428 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
429 self.assertRaises(TypeError, ctx.use_certificate, X509(), "hello, world")
430
431
432 def test_use_certificate_uninitialized(self):
433 """
434 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
435 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
436 initialized (ie, which does not actually have any certificate data).
437 """
438 ctx = Context(TLSv1_METHOD)
439 self.assertRaises(Error, ctx.use_certificate, X509())
440
441
442 def test_use_certificate(self):
443 """
444 :py:obj:`Context.use_certificate` sets the certificate which will be
445 used to identify connections created using the context.
446 """
447 # TODO
448 # Hard to assert anything. But we could set a privatekey then ask
449 # OpenSSL if the cert and key agree using check_privatekey. Then as
450 # long as check_privatekey works right we're good...
451 ctx = Context(TLSv1_METHOD)
452 ctx.use_certificate(load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
453
454
455 def test_use_certificate_file_wrong_args(self):
456 """
457 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
458 called with zero arguments or more than two arguments, or if the first
459 argument is not a byte string or the second argumnent is not an integer.
460 """
461 ctx = Context(TLSv1_METHOD)
462 self.assertRaises(TypeError, ctx.use_certificate_file)
463 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile", object())
464 self.assertRaises(
465 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM, object())
466 self.assertRaises(
467 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
468 self.assertRaises(
469 TypeError, ctx.use_certificate_file, b"somefile", object())
470
471
472 def test_use_certificate_file_missing(self):
473 """
474 :py:obj:`Context.use_certificate_file` raises
475 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does not
476 exist.
477 """
478 ctx = Context(TLSv1_METHOD)
479 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
480
481
482 def test_use_certificate_file(self):
483 """
484 :py:obj:`Context.use_certificate` sets the certificate which will be
485 used to identify connections created using the context.
486 """
487 # TODO
488 # Hard to assert anything. But we could set a privatekey then ask
489 # OpenSSL if the cert and key agree using check_privatekey. Then as
490 # long as check_privatekey works right we're good...
491 pem_filename = self.mktemp()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500492 with open(pem_filename, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800493 pem_file.write(cleartextCertificatePEM)
494
495 ctx = Context(TLSv1_METHOD)
496 ctx.use_certificate_file(pem_filename)
497
498
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500499 if not PY3:
500 def test_use_certificate_file_long(self):
501 """
502 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
503 filetype of type :py:obj:`long` as well as :py:obj:`int`.
504 """
505 pem_filename = self.mktemp()
506 with open(pem_filename, "wb") as pem_file:
507 pem_file.write(cleartextCertificatePEM)
508
509 ctx = Context(TLSv1_METHOD)
510 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
511
512
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500513 def test_check_privatekey_valid(self):
514 """
515 :py:obj:`Context.check_privatekey` returns :py:obj:`None` if the
516 :py:obj:`Context` instance has been configured to use a matched key and
517 certificate pair.
518 """
519 key = load_privatekey(FILETYPE_PEM, client_key_pem)
520 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
521 context = Context(TLSv1_METHOD)
522 context.use_privatekey(key)
523 context.use_certificate(cert)
524 self.assertIs(None, context.check_privatekey())
525
526
527 def test_check_privatekey_invalid(self):
528 """
529 :py:obj:`Context.check_privatekey` raises :py:obj:`Error` if the
530 :py:obj:`Context` instance has been configured to use a key and
531 certificate pair which don't relate to each other.
532 """
533 key = load_privatekey(FILETYPE_PEM, client_key_pem)
534 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
535 context = Context(TLSv1_METHOD)
536 context.use_privatekey(key)
537 context.use_certificate(cert)
538 self.assertRaises(Error, context.check_privatekey)
539
540
541 def test_check_privatekey_wrong_args(self):
542 """
543 :py:obj:`Context.check_privatekey` raises :py:obj:`TypeError` if called
544 with other than no arguments.
545 """
546 context = Context(TLSv1_METHOD)
547 self.assertRaises(TypeError, context.check_privatekey, object())
548
549
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400550 def test_set_app_data_wrong_args(self):
551 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900552 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called with other than
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400553 one argument.
554 """
555 context = Context(TLSv1_METHOD)
556 self.assertRaises(TypeError, context.set_app_data)
557 self.assertRaises(TypeError, context.set_app_data, None, None)
558
559
560 def test_get_app_data_wrong_args(self):
561 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900562 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400563 arguments.
564 """
565 context = Context(TLSv1_METHOD)
566 self.assertRaises(TypeError, context.get_app_data, None)
567
568
569 def test_app_data(self):
570 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900571 :py:obj:`Context.set_app_data` stores an object for later retrieval using
572 :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400573 """
574 app_data = object()
575 context = Context(TLSv1_METHOD)
576 context.set_app_data(app_data)
577 self.assertIdentical(context.get_app_data(), app_data)
578
579
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400580 def test_set_options_wrong_args(self):
581 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900582 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with the wrong
583 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400584 """
585 context = Context(TLSv1_METHOD)
586 self.assertRaises(TypeError, context.set_options)
587 self.assertRaises(TypeError, context.set_options, None)
588 self.assertRaises(TypeError, context.set_options, 1, None)
589
590
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500591 def test_set_options(self):
592 """
593 :py:obj:`Context.set_options` returns the new options value.
594 """
595 context = Context(TLSv1_METHOD)
596 options = context.set_options(OP_NO_SSLv2)
597 self.assertTrue(OP_NO_SSLv2 & options)
598
599
600 if not PY3:
601 def test_set_options_long(self):
602 """
603 On Python 2 :py:obj:`Context.set_options` accepts values of type
604 :py:obj:`long` as well as :py:obj:`int`.
605 """
606 context = Context(TLSv1_METHOD)
607 options = context.set_options(long(OP_NO_SSLv2))
608 self.assertTrue(OP_NO_SSLv2 & options)
609
610
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300611 def test_set_mode_wrong_args(self):
612 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400613 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with the wrong
614 number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300615 """
616 context = Context(TLSv1_METHOD)
617 self.assertRaises(TypeError, context.set_mode)
618 self.assertRaises(TypeError, context.set_mode, None)
619 self.assertRaises(TypeError, context.set_mode, 1, None)
620
621
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400622 if MODE_RELEASE_BUFFERS is not None:
623 def test_set_mode(self):
624 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400625 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the newly
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400626 set mode.
627 """
628 context = Context(TLSv1_METHOD)
629 self.assertTrue(
630 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500631
632 if not PY3:
633 def test_set_mode_long(self):
634 """
635 On Python 2 :py:obj:`Context.set_mode` accepts values of type
636 :py:obj:`long` as well as :py:obj:`int`.
637 """
638 context = Context(TLSv1_METHOD)
639 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
640 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400641 else:
642 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
643
644
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400645 def test_set_timeout_wrong_args(self):
646 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900647 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with the wrong
648 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400649 """
650 context = Context(TLSv1_METHOD)
651 self.assertRaises(TypeError, context.set_timeout)
652 self.assertRaises(TypeError, context.set_timeout, None)
653 self.assertRaises(TypeError, context.set_timeout, 1, None)
654
655
656 def test_get_timeout_wrong_args(self):
657 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900658 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400659 """
660 context = Context(TLSv1_METHOD)
661 self.assertRaises(TypeError, context.get_timeout, None)
662
663
664 def test_timeout(self):
665 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900666 :py:obj:`Context.set_timeout` sets the session timeout for all connections
667 created using the context object. :py:obj:`Context.get_timeout` retrieves this
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400668 value.
669 """
670 context = Context(TLSv1_METHOD)
671 context.set_timeout(1234)
672 self.assertEquals(context.get_timeout(), 1234)
673
674
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500675 if not PY3:
676 def test_timeout_long(self):
677 """
678 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
679 `long` as well as int.
680 """
681 context = Context(TLSv1_METHOD)
682 context.set_timeout(long(1234))
683 self.assertEquals(context.get_timeout(), 1234)
684
685
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400686 def test_set_verify_depth_wrong_args(self):
687 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900688 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called with the wrong
689 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400690 """
691 context = Context(TLSv1_METHOD)
692 self.assertRaises(TypeError, context.set_verify_depth)
693 self.assertRaises(TypeError, context.set_verify_depth, None)
694 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
695
696
697 def test_get_verify_depth_wrong_args(self):
698 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900699 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400700 """
701 context = Context(TLSv1_METHOD)
702 self.assertRaises(TypeError, context.get_verify_depth, None)
703
704
705 def test_verify_depth(self):
706 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900707 :py:obj:`Context.set_verify_depth` sets the number of certificates in a chain
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400708 to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900709 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400710 """
711 context = Context(TLSv1_METHOD)
712 context.set_verify_depth(11)
713 self.assertEquals(context.get_verify_depth(), 11)
714
715
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500716 if not PY3:
717 def test_verify_depth_long(self):
718 """
719 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
720 type `long` as well as int.
721 """
722 context = Context(TLSv1_METHOD)
723 context.set_verify_depth(long(11))
724 self.assertEquals(context.get_verify_depth(), 11)
725
726
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400727 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400728 """
729 Write a new private key out to a new file, encrypted using the given
730 passphrase. Return the path to the new file.
731 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400732 key = PKey()
733 key.generate_key(TYPE_RSA, 128)
734 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400735 fObj = open(pemFile, 'w')
736 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
737 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400738 fObj.close()
739 return pemFile
740
741
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400742 def test_set_passwd_cb_wrong_args(self):
743 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900744 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called with the
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400745 wrong arguments or with a non-callable first argument.
746 """
747 context = Context(TLSv1_METHOD)
748 self.assertRaises(TypeError, context.set_passwd_cb)
749 self.assertRaises(TypeError, context.set_passwd_cb, None)
750 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
751
752
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400753 def test_set_passwd_cb(self):
754 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900755 :py:obj:`Context.set_passwd_cb` accepts a callable which will be invoked when
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400756 a private key is loaded from an encrypted PEM.
757 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400758 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400759 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400760 calledWith = []
761 def passphraseCallback(maxlen, verify, extra):
762 calledWith.append((maxlen, verify, extra))
763 return passphrase
764 context = Context(TLSv1_METHOD)
765 context.set_passwd_cb(passphraseCallback)
766 context.use_privatekey_file(pemFile)
767 self.assertTrue(len(calledWith), 1)
768 self.assertTrue(isinstance(calledWith[0][0], int))
769 self.assertTrue(isinstance(calledWith[0][1], int))
770 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400771
772
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400773 def test_passwd_callback_exception(self):
774 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900775 :py:obj:`Context.use_privatekey_file` propagates any exception raised by the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400776 passphrase callback.
777 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400778 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400779 def passphraseCallback(maxlen, verify, extra):
780 raise RuntimeError("Sorry, I am a fail.")
781
782 context = Context(TLSv1_METHOD)
783 context.set_passwd_cb(passphraseCallback)
784 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
785
786
787 def test_passwd_callback_false(self):
788 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900789 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400790 passphrase callback returns a false value.
791 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400792 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400793 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500794 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400795
796 context = Context(TLSv1_METHOD)
797 context.set_passwd_cb(passphraseCallback)
798 self.assertRaises(Error, context.use_privatekey_file, pemFile)
799
800
801 def test_passwd_callback_non_string(self):
802 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900803 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400804 passphrase callback returns a true non-string value.
805 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400806 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400807 def passphraseCallback(maxlen, verify, extra):
808 return 10
809
810 context = Context(TLSv1_METHOD)
811 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800812 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400813
814
815 def test_passwd_callback_too_long(self):
816 """
817 If the passphrase returned by the passphrase callback returns a string
818 longer than the indicated maximum length, it is truncated.
819 """
820 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400821 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400822 pemFile = self._write_encrypted_pem(passphrase)
823 def passphraseCallback(maxlen, verify, extra):
824 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400825 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400826
827 context = Context(TLSv1_METHOD)
828 context.set_passwd_cb(passphraseCallback)
829 # This shall succeed because the truncated result is the correct
830 # passphrase.
831 context.use_privatekey_file(pemFile)
832
833
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400834 def test_set_info_callback(self):
835 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900836 :py:obj:`Context.set_info_callback` accepts a callable which will be invoked
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400837 when certain information about an SSL connection is available.
838 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500839 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400840
841 clientSSL = Connection(Context(TLSv1_METHOD), client)
842 clientSSL.set_connect_state()
843
844 called = []
845 def info(conn, where, ret):
846 called.append((conn, where, ret))
847 context = Context(TLSv1_METHOD)
848 context.set_info_callback(info)
849 context.use_certificate(
850 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
851 context.use_privatekey(
852 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
853
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400854 serverSSL = Connection(context, server)
855 serverSSL.set_accept_state()
856
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500857 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400858
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500859 # The callback must always be called with a Connection instance as the
860 # first argument. It would probably be better to split this into
861 # separate tests for client and server side info callbacks so we could
862 # assert it is called with the right Connection instance. It would
863 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500864 notConnections = [
865 conn for (conn, where, ret) in called
866 if not isinstance(conn, Connection)]
867 self.assertEqual(
868 [], notConnections,
869 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400870
871
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400872 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400873 """
874 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400875 its :py:obj:`load_verify_locations` method with the given arguments.
876 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400877 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500878 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400879
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400880 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400881 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400882 # Require that the server certificate verify properly or the
883 # connection will fail.
884 clientContext.set_verify(
885 VERIFY_PEER,
886 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
887
888 clientSSL = Connection(clientContext, client)
889 clientSSL.set_connect_state()
890
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400891 serverContext = Context(TLSv1_METHOD)
892 serverContext.use_certificate(
893 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
894 serverContext.use_privatekey(
895 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
896
897 serverSSL = Connection(serverContext, server)
898 serverSSL.set_accept_state()
899
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400900 # Without load_verify_locations above, the handshake
901 # will fail:
902 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
903 # 'certificate verify failed')]
904 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400905
906 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400907 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400908
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500909
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400910 def test_load_verify_file(self):
911 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900912 :py:obj:`Context.load_verify_locations` accepts a file name and uses the
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400913 certificates within for verification purposes.
914 """
915 cafile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400916 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400917 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400918 fObj.close()
919
920 self._load_verify_locations_test(cafile)
921
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400922
Abraham Martinef063482015-03-25 14:06:24 +0000923 def test_load_verify_warning(self):
924 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -0400925 :py:obj:`Context.load_verify_locations` accepts a file name and uses
926 the certificates within for verification purposes. Raises a warning
927 when using a text in cafile.
Abraham Martinef063482015-03-25 14:06:24 +0000928 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -0400929 cafile = self.mktemp().decode("utf-8")
930 with open(cafile, 'w') as fObj:
931 fObj.write(cleartextCertificatePEM.decode("ascii"))
Abraham Martinef063482015-03-25 14:06:24 +0000932
933 with catch_warnings(record=True) as w:
934 simplefilter("always")
Jean-Paul Calderone6462b072015-03-29 07:03:11 -0400935 self._load_verify_locations_test(cafile)
936 self.assertEqual(
937 u"{} for cafile is no longer accepted, use bytes".format(
938 WARNING_TYPE_EXPECTED
939 ),
940 str(w[-1].message)
941 )
942 self.assertIs(DeprecationWarning, w[-1].category)
Abraham Martinef063482015-03-25 14:06:24 +0000943
944
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400945 def test_load_verify_invalid_file(self):
946 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900947 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when passed a
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400948 non-existent cafile.
949 """
950 clientContext = Context(TLSv1_METHOD)
951 self.assertRaises(
952 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400953
954
955 def test_load_verify_directory(self):
956 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900957 :py:obj:`Context.load_verify_locations` accepts a directory name and uses
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400958 the certificates within for verification purposes.
959 """
960 capath = self.mktemp()
961 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400962 # Hash values computed manually with c_rehash to avoid depending on
963 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
964 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500965 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400966 cafile = join(capath, name)
967 fObj = open(cafile, 'w')
968 fObj.write(cleartextCertificatePEM.decode('ascii'))
969 fObj.close()
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400970
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400971 self._load_verify_locations_test(None, capath)
972
973
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400974 def test_load_verify_locations_wrong_args(self):
975 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900976 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if called with
977 the wrong number of arguments or with non-:py:obj:`str` arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400978 """
979 context = Context(TLSv1_METHOD)
980 self.assertRaises(TypeError, context.load_verify_locations)
981 self.assertRaises(TypeError, context.load_verify_locations, object())
982 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
983 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
984
985
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400986 if platform == "win32":
987 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400988 "See LP#404343 and LP#404344."
989 else:
990 def test_set_default_verify_paths(self):
991 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900992 :py:obj:`Context.set_default_verify_paths` causes the platform-specific CA
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400993 certificate locations to be used for verification purposes.
994 """
995 # Testing this requires a server with a certificate signed by one of
996 # the CAs in the platform CA location. Getting one of those costs
997 # money. Fortunately (or unfortunately, depending on your
998 # perspective), it's easy to think of a public server on the
999 # internet which has such a certificate. Connecting to the network
1000 # in a unit test is bad, but it's the only way I can think of to
1001 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001002
Alex Gaynorb586da32014-11-15 09:22:21 -08001003 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
1004 context = Context(TLSv1_METHOD)
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001005 context.set_default_verify_paths()
1006 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02001007 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001008 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001009
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001010 client = socket()
1011 client.connect(('verisign.com', 443))
1012 clientSSL = Connection(context, client)
1013 clientSSL.set_connect_state()
1014 clientSSL.do_handshake()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001015 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001016 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001017
1018
1019 def test_set_default_verify_paths_signature(self):
1020 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001021 :py:obj:`Context.set_default_verify_paths` takes no arguments and raises
1022 :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001023 """
1024 context = Context(TLSv1_METHOD)
1025 self.assertRaises(TypeError, context.set_default_verify_paths, None)
1026 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
1027 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001028
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001029
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001030 def test_add_extra_chain_cert_invalid_cert(self):
1031 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001032 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if called with
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001033 other than one argument or if called with an object which is not an
Jonathan Ballet648875f2011-07-16 14:14:58 +09001034 instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001035 """
1036 context = Context(TLSv1_METHOD)
1037 self.assertRaises(TypeError, context.add_extra_chain_cert)
1038 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
1039 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
1040
1041
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001042 def _handshake_test(self, serverContext, clientContext):
1043 """
1044 Verify that a client and server created with the given contexts can
1045 successfully handshake and communicate.
1046 """
1047 serverSocket, clientSocket = socket_pair()
1048
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001049 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001050 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001051
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001052 client = Connection(clientContext, clientSocket)
1053 client.set_connect_state()
1054
1055 # Make them talk to each other.
1056 # self._interactInMemory(client, server)
1057 for i in range(3):
1058 for s in [client, server]:
1059 try:
1060 s.do_handshake()
1061 except WantReadError:
1062 pass
1063
1064
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001065 def test_set_verify_callback_connection_argument(self):
1066 """
1067 The first argument passed to the verify callback is the
1068 :py:class:`Connection` instance for which verification is taking place.
1069 """
1070 serverContext = Context(TLSv1_METHOD)
1071 serverContext.use_privatekey(
1072 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1073 serverContext.use_certificate(
1074 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1075 serverConnection = Connection(serverContext, None)
1076
1077 class VerifyCallback(object):
1078 def callback(self, connection, *args):
1079 self.connection = connection
1080 return 1
1081
1082 verify = VerifyCallback()
1083 clientContext = Context(TLSv1_METHOD)
1084 clientContext.set_verify(VERIFY_PEER, verify.callback)
1085 clientConnection = Connection(clientContext, None)
1086 clientConnection.set_connect_state()
1087
1088 self._handshakeInMemory(clientConnection, serverConnection)
1089
1090 self.assertIdentical(verify.connection, clientConnection)
1091
1092
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001093 def test_set_verify_callback_exception(self):
1094 """
1095 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1096 exception, verification fails and the exception is propagated to the
1097 caller of :py:obj:`Connection.do_handshake`.
1098 """
1099 serverContext = Context(TLSv1_METHOD)
1100 serverContext.use_privatekey(
1101 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1102 serverContext.use_certificate(
1103 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1104
1105 clientContext = Context(TLSv1_METHOD)
1106 def verify_callback(*args):
1107 raise Exception("silly verify failure")
1108 clientContext.set_verify(VERIFY_PEER, verify_callback)
1109
1110 exc = self.assertRaises(
1111 Exception, self._handshake_test, serverContext, clientContext)
1112 self.assertEqual("silly verify failure", str(exc))
1113
1114
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001115 def test_add_extra_chain_cert(self):
1116 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001117 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509` instance to add to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001118 the certificate chain.
1119
Jonathan Ballet648875f2011-07-16 14:14:58 +09001120 See :py:obj:`_create_certificate_chain` for the details of the certificate
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001121 chain tested.
1122
1123 The chain is tested by starting a server with scert and connecting
1124 to it with a client which trusts cacert and requires verification to
1125 succeed.
1126 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001127 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001128 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1129
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001130 # Dump the CA certificate to a file because that's the only way to load
1131 # it as a trusted CA in the client context.
1132 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001133 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001134 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001135 fObj.close()
1136
1137 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001138 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001139 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001140 fObj.close()
1141
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001142 # Create the server context
1143 serverContext = Context(TLSv1_METHOD)
1144 serverContext.use_privatekey(skey)
1145 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001146 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001147 serverContext.add_extra_chain_cert(icert)
1148
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001149 # Create the client
1150 clientContext = Context(TLSv1_METHOD)
1151 clientContext.set_verify(
1152 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001153 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001154
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001155 # Try it out.
1156 self._handshake_test(serverContext, clientContext)
1157
1158
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001159 def test_use_certificate_chain_file(self):
1160 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001161 :py:obj:`Context.use_certificate_chain_file` reads a certificate chain from
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001162 the specified file.
1163
1164 The chain is tested by starting a server with scert and connecting
1165 to it with a client which trusts cacert and requires verification to
1166 succeed.
1167 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001168 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001169 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1170
1171 # Write out the chain file.
1172 chainFile = self.mktemp()
Jean-Paul Calderoned8607982014-01-18 10:30:55 -05001173 fObj = open(chainFile, 'wb')
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001174 # Most specific to least general.
Jean-Paul Calderoned8607982014-01-18 10:30:55 -05001175 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1176 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1177 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001178 fObj.close()
1179
1180 serverContext = Context(TLSv1_METHOD)
1181 serverContext.use_certificate_chain_file(chainFile)
1182 serverContext.use_privatekey(skey)
1183
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001184 fObj = open('ca.pem', 'w')
1185 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001186 fObj.close()
1187
1188 clientContext = Context(TLSv1_METHOD)
1189 clientContext.set_verify(
1190 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001191 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001192
1193 self._handshake_test(serverContext, clientContext)
1194
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001195
1196 def test_use_certificate_chain_file_wrong_args(self):
1197 """
1198 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1199 if passed zero or more than one argument or when passed a non-byte
1200 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error` when
1201 passed a bad chain file name (for example, the name of a file which does
1202 not exist).
1203 """
1204 context = Context(TLSv1_METHOD)
1205 self.assertRaises(TypeError, context.use_certificate_chain_file)
1206 self.assertRaises(TypeError, context.use_certificate_chain_file, object())
1207 self.assertRaises(TypeError, context.use_certificate_chain_file, b"foo", object())
1208
1209 self.assertRaises(Error, context.use_certificate_chain_file, self.mktemp())
1210
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001211 # XXX load_client_ca
1212 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001213
1214 def test_get_verify_mode_wrong_args(self):
1215 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001216 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001217 arguments.
1218 """
1219 context = Context(TLSv1_METHOD)
1220 self.assertRaises(TypeError, context.get_verify_mode, None)
1221
1222
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001223 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001224 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001225 :py:obj:`Context.get_verify_mode` returns the verify mode flags previously
1226 passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001227 """
1228 context = Context(TLSv1_METHOD)
1229 self.assertEquals(context.get_verify_mode(), 0)
1230 context.set_verify(
1231 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1232 self.assertEquals(
1233 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1234
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001235
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001236 if not PY3:
1237 def test_set_verify_mode_long(self):
1238 """
1239 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1240 type :py:obj:`long` as well as :py:obj:`int`.
1241 """
1242 context = Context(TLSv1_METHOD)
1243 self.assertEquals(context.get_verify_mode(), 0)
1244 context.set_verify(
1245 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None)
1246 self.assertEquals(
1247 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1248
1249
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001250 def test_load_tmp_dh_wrong_args(self):
1251 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001252 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
1253 number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001254 """
1255 context = Context(TLSv1_METHOD)
1256 self.assertRaises(TypeError, context.load_tmp_dh)
1257 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1258 self.assertRaises(TypeError, context.load_tmp_dh, object())
1259
1260
1261 def test_load_tmp_dh_missing_file(self):
1262 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001263 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the specified file
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001264 does not exist.
1265 """
1266 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001267 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001268
1269
1270 def test_load_tmp_dh(self):
1271 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001272 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001273 specified file.
1274 """
1275 context = Context(TLSv1_METHOD)
1276 dhfilename = self.mktemp()
1277 dhfile = open(dhfilename, "w")
1278 dhfile.write(dhparam)
1279 dhfile.close()
1280 context.load_tmp_dh(dhfilename)
1281 # XXX What should I assert here? -exarkun
1282
1283
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001284 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001285 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001286 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001287 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001288 """
1289 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001290 for curve in get_elliptic_curves():
1291 # The only easily "assertable" thing is that it does not raise an
1292 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001293 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001294
1295
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001296 def test_set_cipher_list_bytes(self):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001297 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001298 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
1299 ciphers which connections created with the context object will be able
1300 to choose from.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001301 """
1302 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001303 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001304 conn = Connection(context, None)
1305 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001306
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001307
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001308 def test_set_cipher_list_text(self):
1309 """
1310 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
1311 the ciphers which connections created with the context object will be
1312 able to choose from.
1313 """
1314 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -05001315 context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001316 conn = Connection(context, None)
1317 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
1318
1319
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001320 def test_set_cipher_list_wrong_args(self):
1321 """
Jean-Paul Calderone17044832014-01-18 10:20:11 -05001322 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
1323 passed zero arguments or more than one argument or when passed a
1324 non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001325 passed an incorrect cipher list string.
1326 """
1327 context = Context(TLSv1_METHOD)
1328 self.assertRaises(TypeError, context.set_cipher_list)
1329 self.assertRaises(TypeError, context.set_cipher_list, object())
1330 self.assertRaises(TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object())
1331
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001332 self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001333
1334
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001335 def test_set_session_cache_mode_wrong_args(self):
1336 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001337 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1338 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001339 """
1340 context = Context(TLSv1_METHOD)
1341 self.assertRaises(TypeError, context.set_session_cache_mode)
1342 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1343
1344
1345 def test_get_session_cache_mode_wrong_args(self):
1346 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001347 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1348 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001349 """
1350 context = Context(TLSv1_METHOD)
1351 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1352
1353
1354 def test_session_cache_mode(self):
1355 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001356 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1357 cached. The setting can be retrieved via
1358 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001359 """
1360 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001361 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001362 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1363 self.assertEqual(SESS_CACHE_OFF, off)
1364 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1365
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001366 if not PY3:
1367 def test_session_cache_mode_long(self):
1368 """
1369 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1370 of type :py:obj:`long` as well as :py:obj:`int`.
1371 """
1372 context = Context(TLSv1_METHOD)
1373 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1374 self.assertEqual(
1375 SESS_CACHE_BOTH, context.get_session_cache_mode())
1376
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001377
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001378 def test_get_cert_store(self):
1379 """
1380 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store` instance.
1381 """
1382 context = Context(TLSv1_METHOD)
1383 store = context.get_cert_store()
1384 self.assertIsInstance(store, X509Store)
1385
1386
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001387
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001388class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1389 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001390 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
1391 :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001392 """
1393 def test_wrong_args(self):
1394 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001395 :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001396 with other than one argument.
1397 """
1398 context = Context(TLSv1_METHOD)
1399 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1400 self.assertRaises(
1401 TypeError, context.set_tlsext_servername_callback, 1, 2)
1402
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001403
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001404 def test_old_callback_forgotten(self):
1405 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001406 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001407 callback, the one it replaces is dereferenced.
1408 """
1409 def callback(connection):
1410 pass
1411
1412 def replacement(connection):
1413 pass
1414
1415 context = Context(TLSv1_METHOD)
1416 context.set_tlsext_servername_callback(callback)
1417
1418 tracker = ref(callback)
1419 del callback
1420
1421 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001422
1423 # One run of the garbage collector happens to work on CPython. PyPy
1424 # doesn't collect the underlying object until a second run for whatever
1425 # reason. That's fine, it still demonstrates our code has properly
1426 # dropped the reference.
1427 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001428 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001429
1430 callback = tracker()
1431 if callback is not None:
1432 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001433 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001434 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001435
1436
1437 def test_no_servername(self):
1438 """
1439 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001440 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
1441 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001442 """
1443 args = []
1444 def servername(conn):
1445 args.append((conn, conn.get_servername()))
1446 context = Context(TLSv1_METHOD)
1447 context.set_tlsext_servername_callback(servername)
1448
1449 # Lose our reference to it. The Context is responsible for keeping it
1450 # alive now.
1451 del servername
1452 collect()
1453
1454 # Necessary to actually accept the connection
1455 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1456 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1457
1458 # Do a little connection to trigger the logic
1459 server = Connection(context, None)
1460 server.set_accept_state()
1461
1462 client = Connection(Context(TLSv1_METHOD), None)
1463 client.set_connect_state()
1464
1465 self._interactInMemory(server, client)
1466
1467 self.assertEqual([(server, None)], args)
1468
1469
1470 def test_servername(self):
1471 """
1472 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +09001473 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
1474 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001475 """
1476 args = []
1477 def servername(conn):
1478 args.append((conn, conn.get_servername()))
1479 context = Context(TLSv1_METHOD)
1480 context.set_tlsext_servername_callback(servername)
1481
1482 # Necessary to actually accept the connection
1483 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1484 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1485
1486 # Do a little connection to trigger the logic
1487 server = Connection(context, None)
1488 server.set_accept_state()
1489
1490 client = Connection(Context(TLSv1_METHOD), None)
1491 client.set_connect_state()
1492 client.set_tlsext_host_name(b("foo1.example.com"))
1493
1494 self._interactInMemory(server, client)
1495
1496 self.assertEqual([(server, b("foo1.example.com"))], args)
1497
1498
1499
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001500class SessionTests(TestCase):
1501 """
1502 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1503 """
1504 def test_construction(self):
1505 """
1506 :py:class:`Session` can be constructed with no arguments, creating a new
1507 instance of that type.
1508 """
1509 new_session = Session()
1510 self.assertTrue(isinstance(new_session, Session))
1511
1512
1513 def test_construction_wrong_args(self):
1514 """
1515 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
1516 is raised.
1517 """
1518 self.assertRaises(TypeError, Session, 123)
1519 self.assertRaises(TypeError, Session, "hello")
1520 self.assertRaises(TypeError, Session, object())
1521
1522
1523
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001524class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05001525 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001526 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001527 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001528 # XXX get_peer_certificate -> None
1529 # XXX sock_shutdown
1530 # XXX master_key -> TypeError
1531 # XXX server_random -> TypeError
1532 # XXX state_string
1533 # XXX connect -> TypeError
1534 # XXX connect_ex -> TypeError
1535 # XXX set_connect_state -> TypeError
1536 # XXX set_accept_state -> TypeError
1537 # XXX renegotiate_pending
1538 # XXX do_handshake -> TypeError
1539 # XXX bio_read -> TypeError
1540 # XXX recv -> TypeError
1541 # XXX send -> TypeError
1542 # XXX bio_write -> TypeError
1543
Rick Deane15b1472009-07-09 15:53:42 -05001544 def test_type(self):
1545 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001546 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001547 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05001548 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001549 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05001550 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001551 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05001552
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001553
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001554 def test_get_context(self):
1555 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001556 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
1557 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001558 """
1559 context = Context(TLSv1_METHOD)
1560 connection = Connection(context, None)
1561 self.assertIdentical(connection.get_context(), context)
1562
1563
1564 def test_get_context_wrong_args(self):
1565 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001566 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001567 arguments.
1568 """
1569 connection = Connection(Context(TLSv1_METHOD), None)
1570 self.assertRaises(TypeError, connection.get_context, None)
1571
1572
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001573 def test_set_context_wrong_args(self):
1574 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001575 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
1576 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001577 than 1.
1578 """
1579 ctx = Context(TLSv1_METHOD)
1580 connection = Connection(ctx, None)
1581 self.assertRaises(TypeError, connection.set_context)
1582 self.assertRaises(TypeError, connection.set_context, object())
1583 self.assertRaises(TypeError, connection.set_context, "hello")
1584 self.assertRaises(TypeError, connection.set_context, 1)
1585 self.assertRaises(TypeError, connection.set_context, 1, 2)
1586 self.assertRaises(
1587 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
1588 self.assertIdentical(ctx, connection.get_context())
1589
1590
1591 def test_set_context(self):
1592 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001593 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001594 for the connection.
1595 """
1596 original = Context(SSLv23_METHOD)
1597 replacement = Context(TLSv1_METHOD)
1598 connection = Connection(original, None)
1599 connection.set_context(replacement)
1600 self.assertIdentical(replacement, connection.get_context())
1601 # Lose our references to the contexts, just in case the Connection isn't
1602 # properly managing its own contributions to their reference counts.
1603 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001604 collect()
1605
1606
1607 def test_set_tlsext_host_name_wrong_args(self):
1608 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001609 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001610 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09001611 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001612 """
1613 conn = Connection(Context(TLSv1_METHOD), None)
1614 self.assertRaises(TypeError, conn.set_tlsext_host_name)
1615 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
1616 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
1617 self.assertRaises(
1618 TypeError, conn.set_tlsext_host_name, b("with\0null"))
1619
Abraham Martinc5484ba2015-03-25 15:33:05 +00001620 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001621 # On Python 3.x, don't accidentally implicitly convert from text.
1622 self.assertRaises(
1623 TypeError,
1624 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001625
1626
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001627 def test_get_servername_wrong_args(self):
1628 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001629 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001630 arguments.
1631 """
1632 connection = Connection(Context(TLSv1_METHOD), None)
1633 self.assertRaises(TypeError, connection.get_servername, object())
1634 self.assertRaises(TypeError, connection.get_servername, 1)
1635 self.assertRaises(TypeError, connection.get_servername, "hello")
1636
1637
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001638 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001639 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001640 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001641 immediate read.
1642 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001643 connection = Connection(Context(TLSv1_METHOD), None)
1644 self.assertEquals(connection.pending(), 0)
1645
1646
1647 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001648 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001649 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001650 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001651 connection = Connection(Context(TLSv1_METHOD), None)
1652 self.assertRaises(TypeError, connection.pending, None)
1653
1654
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001655 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001656 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001657 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001658 argument or with the wrong number of arguments.
1659 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001660 connection = Connection(Context(TLSv1_METHOD), socket())
1661 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001662 self.assertRaises(TypeError, connection.connect)
1663 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001664
1665
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001666 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001667 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001668 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001669 connect method raises it.
1670 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001671 client = socket()
1672 context = Context(TLSv1_METHOD)
1673 clientSSL = Connection(context, client)
1674 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04001675 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001676
1677
1678 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001679 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001680 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001681 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001682 port = socket()
1683 port.bind(('', 0))
1684 port.listen(3)
1685
1686 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001687 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
1688 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001689
1690
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001691 if platform == "darwin":
1692 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
1693 else:
1694 def test_connect_ex(self):
1695 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001696 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001697 errno instead of raising an exception.
1698 """
1699 port = socket()
1700 port.bind(('', 0))
1701 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001702
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001703 clientSSL = Connection(Context(TLSv1_METHOD), socket())
1704 clientSSL.setblocking(False)
1705 result = clientSSL.connect_ex(port.getsockname())
1706 expected = (EINPROGRESS, EWOULDBLOCK)
1707 self.assertTrue(
1708 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001709
1710
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001711 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001712 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001713 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001714 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001715 connection = Connection(Context(TLSv1_METHOD), socket())
1716 self.assertRaises(TypeError, connection.accept, None)
1717
1718
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001719 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001720 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001721 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
1722 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001723 connection originated from.
1724 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001725 ctx = Context(TLSv1_METHOD)
1726 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1727 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001728 port = socket()
1729 portSSL = Connection(ctx, port)
1730 portSSL.bind(('', 0))
1731 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001732
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001733 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001734
1735 # Calling portSSL.getsockname() here to get the server IP address sounds
1736 # great, but frequently fails on Windows.
1737 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001738
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001739 serverSSL, address = portSSL.accept()
1740
1741 self.assertTrue(isinstance(serverSSL, Connection))
1742 self.assertIdentical(serverSSL.get_context(), ctx)
1743 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001744
1745
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001746 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001747 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001748 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001749 number of arguments or with arguments other than integers.
1750 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001751 connection = Connection(Context(TLSv1_METHOD), None)
1752 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04001753 self.assertRaises(TypeError, connection.get_shutdown, None)
1754 self.assertRaises(TypeError, connection.set_shutdown)
1755 self.assertRaises(TypeError, connection.set_shutdown, None)
1756 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001757
1758
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001759 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001760 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001761 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001762 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001763 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001764 self.assertFalse(server.shutdown())
1765 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001766 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001767 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
1768 client.shutdown()
1769 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
1770 self.assertRaises(ZeroReturnError, server.recv, 1024)
1771 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001772
1773
Paul Aurichc85e0862015-01-08 08:34:33 -08001774 def test_shutdown_closed(self):
1775 """
1776 If the underlying socket is closed, :py:obj:`Connection.shutdown` propagates the
1777 write error from the low level write call.
1778 """
1779 server, client = self._loopback()
1780 server.sock_shutdown(2)
1781 exc = self.assertRaises(SysCallError, server.shutdown)
1782 if platform == "win32":
1783 self.assertEqual(exc.args[0], ESHUTDOWN)
1784 else:
1785 self.assertEqual(exc.args[0], EPIPE)
1786
1787
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001788 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001789 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001790 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001791 process.
1792 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001793 connection = Connection(Context(TLSv1_METHOD), socket())
1794 connection.set_shutdown(RECEIVED_SHUTDOWN)
1795 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1796
1797
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05001798 if not PY3:
1799 def test_set_shutdown_long(self):
1800 """
1801 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
1802 of type :py:obj:`long` as well as :py:obj:`int`.
1803 """
1804 connection = Connection(Context(TLSv1_METHOD), socket())
1805 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
1806 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1807
1808
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001809 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001810 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001811 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
1812 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001813 with any arguments.
1814 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001815 conn = Connection(Context(TLSv1_METHOD), None)
1816 self.assertRaises(TypeError, conn.get_app_data, None)
1817 self.assertRaises(TypeError, conn.set_app_data)
1818 self.assertRaises(TypeError, conn.set_app_data, None, None)
1819
1820
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001821 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001822 """
1823 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001824 :py:obj:`Connection.set_app_data` and later retrieved with
1825 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001826 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001827 conn = Connection(Context(TLSv1_METHOD), None)
1828 app_data = object()
1829 conn.set_app_data(app_data)
1830 self.assertIdentical(conn.get_app_data(), app_data)
1831
1832
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001833 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001834 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001835 :py:obj:`Connection.makefile` is not implemented and calling that method raises
1836 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001837 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001838 conn = Connection(Context(TLSv1_METHOD), None)
1839 self.assertRaises(NotImplementedError, conn.makefile)
1840
1841
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001842 def test_get_peer_cert_chain_wrong_args(self):
1843 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001844 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001845 arguments.
1846 """
1847 conn = Connection(Context(TLSv1_METHOD), None)
1848 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
1849 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
1850 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
1851 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
1852
1853
1854 def test_get_peer_cert_chain(self):
1855 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001856 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001857 the connected server returned for the certification verification.
1858 """
1859 chain = _create_certificate_chain()
1860 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1861
1862 serverContext = Context(TLSv1_METHOD)
1863 serverContext.use_privatekey(skey)
1864 serverContext.use_certificate(scert)
1865 serverContext.add_extra_chain_cert(icert)
1866 serverContext.add_extra_chain_cert(cacert)
1867 server = Connection(serverContext, None)
1868 server.set_accept_state()
1869
1870 # Create the client
1871 clientContext = Context(TLSv1_METHOD)
1872 clientContext.set_verify(VERIFY_NONE, verify_cb)
1873 client = Connection(clientContext, None)
1874 client.set_connect_state()
1875
1876 self._interactInMemory(client, server)
1877
1878 chain = client.get_peer_cert_chain()
1879 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001880 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001881 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001882 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001883 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001884 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001885 "Authority Certificate", chain[2].get_subject().CN)
1886
1887
1888 def test_get_peer_cert_chain_none(self):
1889 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001890 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001891 certificate chain.
1892 """
1893 ctx = Context(TLSv1_METHOD)
1894 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1895 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1896 server = Connection(ctx, None)
1897 server.set_accept_state()
1898 client = Connection(Context(TLSv1_METHOD), None)
1899 client.set_connect_state()
1900 self._interactInMemory(client, server)
1901 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001902
1903
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001904 def test_get_session_wrong_args(self):
1905 """
1906 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
1907 with any arguments.
1908 """
1909 ctx = Context(TLSv1_METHOD)
1910 server = Connection(ctx, None)
1911 self.assertRaises(TypeError, server.get_session, 123)
1912 self.assertRaises(TypeError, server.get_session, "hello")
1913 self.assertRaises(TypeError, server.get_session, object())
1914
1915
1916 def test_get_session_unconnected(self):
1917 """
1918 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
1919 an object which has not been connected.
1920 """
1921 ctx = Context(TLSv1_METHOD)
1922 server = Connection(ctx, None)
1923 session = server.get_session()
1924 self.assertIdentical(None, session)
1925
1926
1927 def test_server_get_session(self):
1928 """
1929 On the server side of a connection, :py:obj:`Connection.get_session`
1930 returns a :py:class:`Session` instance representing the SSL session for
1931 that connection.
1932 """
1933 server, client = self._loopback()
1934 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001935 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001936
1937
1938 def test_client_get_session(self):
1939 """
1940 On the client side of a connection, :py:obj:`Connection.get_session`
1941 returns a :py:class:`Session` instance representing the SSL session for
1942 that connection.
1943 """
1944 server, client = self._loopback()
1945 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001946 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001947
1948
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05001949 def test_set_session_wrong_args(self):
1950 """
1951 If called with an object that is not an instance of :py:class:`Session`,
1952 or with other than one argument, :py:obj:`Connection.set_session` raises
1953 :py:obj:`TypeError`.
1954 """
1955 ctx = Context(TLSv1_METHOD)
1956 connection = Connection(ctx, None)
1957 self.assertRaises(TypeError, connection.set_session)
1958 self.assertRaises(TypeError, connection.set_session, 123)
1959 self.assertRaises(TypeError, connection.set_session, "hello")
1960 self.assertRaises(TypeError, connection.set_session, object())
1961 self.assertRaises(
1962 TypeError, connection.set_session, Session(), Session())
1963
1964
1965 def test_client_set_session(self):
1966 """
1967 :py:obj:`Connection.set_session`, when used prior to a connection being
1968 established, accepts a :py:class:`Session` instance and causes an
1969 attempt to re-use the session it represents when the SSL handshake is
1970 performed.
1971 """
1972 key = load_privatekey(FILETYPE_PEM, server_key_pem)
1973 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
1974 ctx = Context(TLSv1_METHOD)
1975 ctx.use_privatekey(key)
1976 ctx.use_certificate(cert)
1977 ctx.set_session_id("unity-test")
1978
1979 def makeServer(socket):
1980 server = Connection(ctx, socket)
1981 server.set_accept_state()
1982 return server
1983
1984 originalServer, originalClient = self._loopback(
1985 serverFactory=makeServer)
1986 originalSession = originalClient.get_session()
1987
1988 def makeClient(socket):
1989 client = self._loopbackClientFactory(socket)
1990 client.set_session(originalSession)
1991 return client
1992 resumedServer, resumedClient = self._loopback(
1993 serverFactory=makeServer,
1994 clientFactory=makeClient)
1995
1996 # This is a proxy: in general, we have no access to any unique
1997 # identifier for the session (new enough versions of OpenSSL expose a
1998 # hash which could be usable, but "new enough" is very, very new).
1999 # Instead, exploit the fact that the master key is re-used if the
2000 # session is re-used. As long as the master key for the two connections
2001 # is the same, the session was re-used!
2002 self.assertEqual(
2003 originalServer.master_key(), resumedServer.master_key())
2004
2005
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002006 def test_set_session_wrong_method(self):
2007 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002008 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
2009 instance associated with a context using a different SSL method than the
2010 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
2011 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002012 """
2013 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2014 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2015 ctx = Context(TLSv1_METHOD)
2016 ctx.use_privatekey(key)
2017 ctx.use_certificate(cert)
2018 ctx.set_session_id("unity-test")
2019
2020 def makeServer(socket):
2021 server = Connection(ctx, socket)
2022 server.set_accept_state()
2023 return server
2024
2025 originalServer, originalClient = self._loopback(
2026 serverFactory=makeServer)
2027 originalSession = originalClient.get_session()
2028
2029 def makeClient(socket):
2030 # Intentionally use a different, incompatible method here.
2031 client = Connection(Context(SSLv3_METHOD), socket)
2032 client.set_connect_state()
2033 client.set_session(originalSession)
2034 return client
2035
2036 self.assertRaises(
2037 Error,
2038 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2039
2040
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002041 def test_wantWriteError(self):
2042 """
2043 :py:obj:`Connection` methods which generate output raise
2044 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2045 fail indicating a should-write state.
2046 """
2047 client_socket, server_socket = socket_pair()
2048 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002049 # anything. Only write a single byte at a time so we can be sure we
2050 # completely fill the buffer. Even though the socket API is allowed to
2051 # signal a short write via its return value it seems this doesn't
2052 # always happen on all platforms (FreeBSD and OS X particular) for the
2053 # very last bit of available buffer space.
2054 msg = b"x"
2055 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002056 try:
2057 client_socket.send(msg)
2058 except error as e:
2059 if e.errno == EWOULDBLOCK:
2060 break
2061 raise
2062 else:
2063 self.fail(
2064 "Failed to fill socket buffer, cannot test BIO want write")
2065
2066 ctx = Context(TLSv1_METHOD)
2067 conn = Connection(ctx, client_socket)
2068 # Client's speak first, so make it an SSL client
2069 conn.set_connect_state()
2070 self.assertRaises(WantWriteError, conn.do_handshake)
2071
2072 # XXX want_read
2073
Fedor Brunner416f4a12014-03-28 13:18:38 +01002074 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002075 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002076 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2077 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002078 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002079 ctx = Context(TLSv1_METHOD)
2080 connection = Connection(ctx, None)
2081 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002082
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002083
Fedor Brunner416f4a12014-03-28 13:18:38 +01002084 def test_get_peer_finished_before_connect(self):
2085 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002086 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2087 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002088 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002089 ctx = Context(TLSv1_METHOD)
2090 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002091 self.assertEqual(connection.get_peer_finished(), None)
2092
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002093
Fedor Brunner416f4a12014-03-28 13:18:38 +01002094 def test_get_finished(self):
2095 """
2096 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002097 message send from client, or server. Finished messages are send during
2098 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002099 """
2100
Fedor Brunner5747b932014-03-05 14:22:34 +01002101 server, client = self._loopback()
2102
2103 self.assertNotEqual(server.get_finished(), None)
2104 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002105
Jean-Paul Calderoned979f232014-03-30 11:58:00 -04002106
Fedor Brunner416f4a12014-03-28 13:18:38 +01002107 def test_get_peer_finished(self):
2108 """
2109 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002110 message received from client, or server. Finished messages are send
2111 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002112 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002113 server, client = self._loopback()
2114
2115 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002116 self.assertTrue(len(server.get_peer_finished()) > 0)
2117
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002118
Fedor Brunner416f4a12014-03-28 13:18:38 +01002119 def test_tls_finished_message_symmetry(self):
2120 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002121 The TLS Finished message send by server must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002122 received by client.
2123
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002124 The TLS Finished message send by client must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002125 received by server.
2126 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002127 server, client = self._loopback()
2128
Fedor Brunner5747b932014-03-05 14:22:34 +01002129 self.assertEqual(server.get_finished(), client.get_peer_finished())
2130 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002131
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002132
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002133 def test_get_cipher_name_before_connect(self):
2134 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002135 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2136 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002137 """
2138 ctx = Context(TLSv1_METHOD)
2139 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002140 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002141
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002142
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002143 def test_get_cipher_name(self):
2144 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002145 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2146 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002147 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002148 server, client = self._loopback()
2149 server_cipher_name, client_cipher_name = \
2150 server.get_cipher_name(), client.get_cipher_name()
2151
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002152 self.assertIsInstance(server_cipher_name, text_type)
2153 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002154
2155 self.assertEqual(server_cipher_name, client_cipher_name)
2156
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002157
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002158 def test_get_cipher_version_before_connect(self):
2159 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002160 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2161 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002162 """
2163 ctx = Context(TLSv1_METHOD)
2164 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002165 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002166
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002167
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002168 def test_get_cipher_version(self):
2169 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002170 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2171 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002172 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002173 server, client = self._loopback()
2174 server_cipher_version, client_cipher_version = \
2175 server.get_cipher_version(), client.get_cipher_version()
2176
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002177 self.assertIsInstance(server_cipher_version, text_type)
2178 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002179
2180 self.assertEqual(server_cipher_version, client_cipher_version)
2181
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002182
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002183 def test_get_cipher_bits_before_connect(self):
2184 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002185 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2186 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002187 """
2188 ctx = Context(TLSv1_METHOD)
2189 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002190 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002191
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002192
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002193 def test_get_cipher_bits(self):
2194 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002195 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2196 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002197 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002198 server, client = self._loopback()
2199 server_cipher_bits, client_cipher_bits = \
2200 server.get_cipher_bits(), client.get_cipher_bits()
2201
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002202 self.assertIsInstance(server_cipher_bits, int)
2203 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002204
2205 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002206
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002207
2208
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002209class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002210 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002211 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002212 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002213 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002214 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002215 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002216 arguments.
2217 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002218 connection = Connection(Context(TLSv1_METHOD), None)
2219 self.assertRaises(TypeError, connection.get_cipher_list, None)
2220
2221
2222 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002223 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002224 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2225 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002226 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002227 connection = Connection(Context(TLSv1_METHOD), None)
2228 ciphers = connection.get_cipher_list()
2229 self.assertTrue(isinstance(ciphers, list))
2230 for cipher in ciphers:
2231 self.assertTrue(isinstance(cipher, str))
2232
2233
2234
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002235class ConnectionSendTests(TestCase, _LoopbackMixin):
2236 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002237 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002238 """
2239 def test_wrong_args(self):
2240 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002241 When called with arguments other than string argument for its first
2242 parameter or more than two arguments, :py:obj:`Connection.send` raises
2243 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002244 """
2245 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002246 self.assertRaises(TypeError, connection.send)
2247 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002248 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002249
2250
2251 def test_short_bytes(self):
2252 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002253 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002254 and returns the number of bytes sent.
2255 """
2256 server, client = self._loopback()
2257 count = server.send(b('xy'))
2258 self.assertEquals(count, 2)
2259 self.assertEquals(client.recv(2), b('xy'))
2260
Abraham Martinef063482015-03-25 14:06:24 +00002261
2262 def test_text(self):
2263 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002264 When passed a text, :py:obj:`Connection.send` transmits all of it and
2265 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002266 """
2267 server, client = self._loopback()
2268 with catch_warnings(record=True) as w:
2269 simplefilter("always")
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002270 count = server.send(u"xy")
2271 self.assertEqual(
2272 u"{} for buf is no longer accepted, use bytes".format(
2273 WARNING_TYPE_EXPECTED
2274 ),
2275 str(w[-1].message)
2276 )
2277 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinef063482015-03-25 14:06:24 +00002278 self.assertEquals(count, 2)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002279 self.assertEquals(client.recv(2), b"xy")
Abraham Martinef063482015-03-25 14:06:24 +00002280
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002281 try:
2282 memoryview
2283 except NameError:
2284 "cannot test sending memoryview without memoryview"
2285 else:
2286 def test_short_memoryview(self):
2287 """
2288 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002289 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002290 bytes sent.
2291 """
2292 server, client = self._loopback()
2293 count = server.send(memoryview(b('xy')))
2294 self.assertEquals(count, 2)
2295 self.assertEquals(client.recv(2), b('xy'))
2296
2297
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002298 try:
2299 buffer
2300 except NameError:
2301 "cannot test sending buffer without buffer"
2302 else:
2303 def test_short_buffer(self):
2304 """
2305 When passed a buffer containing a small number of bytes,
2306 :py:obj:`Connection.send` transmits all of them and returns the number of
2307 bytes sent.
2308 """
2309 server, client = self._loopback()
2310 count = server.send(buffer(b('xy')))
2311 self.assertEquals(count, 2)
2312 self.assertEquals(client.recv(2), b('xy'))
2313
2314
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002315
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002316class ConnectionSendallTests(TestCase, _LoopbackMixin):
2317 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002318 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002319 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002320 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002321 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002322 When called with arguments other than a string argument for its first
2323 parameter or with more than two arguments, :py:obj:`Connection.sendall`
2324 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002325 """
2326 connection = Connection(Context(TLSv1_METHOD), None)
2327 self.assertRaises(TypeError, connection.sendall)
2328 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002329 self.assertRaises(
2330 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002331
2332
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002333 def test_short(self):
2334 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002335 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002336 it.
2337 """
2338 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04002339 server.sendall(b('x'))
2340 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002341
2342
Abraham Martinef063482015-03-25 14:06:24 +00002343 def test_text(self):
2344 """
2345 :py:obj:`Connection.sendall` transmits all the content in the string passed to
2346 it raising a DepreactionWarning in case of this being a text.
2347 """
2348 server, client = self._loopback()
2349 with catch_warnings(record=True) as w:
2350 simplefilter("always")
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002351 server.sendall(u"x")
2352 self.assertEqual(
2353 u"{} for buf is no longer accepted, use bytes".format(
2354 WARNING_TYPE_EXPECTED
2355 ),
2356 str(w[-1].message)
2357 )
2358 self.assertIs(w[-1].category, DeprecationWarning)
2359 self.assertEquals(client.recv(1), b"x")
Abraham Martinef063482015-03-25 14:06:24 +00002360
2361
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002362 try:
2363 memoryview
2364 except NameError:
2365 "cannot test sending memoryview without memoryview"
2366 else:
2367 def test_short_memoryview(self):
2368 """
2369 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002370 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002371 """
2372 server, client = self._loopback()
2373 server.sendall(memoryview(b('x')))
2374 self.assertEquals(client.recv(1), b('x'))
2375
2376
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002377 try:
2378 buffer
2379 except NameError:
2380 "cannot test sending buffers without buffers"
2381 else:
2382 def test_short_buffers(self):
2383 """
2384 When passed a buffer containing a small number of bytes,
2385 :py:obj:`Connection.sendall` transmits all of them.
2386 """
2387 server, client = self._loopback()
2388 server.sendall(buffer(b('x')))
2389 self.assertEquals(client.recv(1), b('x'))
2390
2391
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002392 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002393 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002394 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002395 it even if this requires multiple calls of an underlying write function.
2396 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002397 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04002398 # Should be enough, underlying SSL_write should only do 16k at a time.
2399 # On Windows, after 32k of bytes the write will block (forever - because
2400 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04002401 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002402 server.sendall(message)
2403 accum = []
2404 received = 0
2405 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04002406 data = client.recv(1024)
2407 accum.append(data)
2408 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04002409 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002410
2411
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002412 def test_closed(self):
2413 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002414 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002415 write error from the low level write call.
2416 """
2417 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04002418 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002419 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02002420 if platform == "win32":
2421 self.assertEqual(exc.args[0], ESHUTDOWN)
2422 else:
2423 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002424
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002425
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002426
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002427class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
2428 """
2429 Tests for SSL renegotiation APIs.
2430 """
2431 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002432 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002433 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002434 arguments.
2435 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002436 connection = Connection(Context(TLSv1_METHOD), None)
2437 self.assertRaises(TypeError, connection.renegotiate, None)
2438
2439
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002440 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002441 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002442 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002443 any arguments.
2444 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002445 connection = Connection(Context(TLSv1_METHOD), None)
2446 self.assertRaises(TypeError, connection.total_renegotiations, None)
2447
2448
2449 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002450 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002451 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002452 renegotiations have happened.
2453 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002454 connection = Connection(Context(TLSv1_METHOD), None)
2455 self.assertEquals(connection.total_renegotiations(), 0)
2456
2457
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002458# def test_renegotiate(self):
2459# """
2460# """
2461# server, client = self._loopback()
2462
2463# server.send("hello world")
2464# self.assertEquals(client.recv(len("hello world")), "hello world")
2465
2466# self.assertEquals(server.total_renegotiations(), 0)
2467# self.assertTrue(server.renegotiate())
2468
2469# server.setblocking(False)
2470# client.setblocking(False)
2471# while server.renegotiate_pending():
2472# client.do_handshake()
2473# server.do_handshake()
2474
2475# self.assertEquals(server.total_renegotiations(), 1)
2476
2477
2478
2479
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002480class ErrorTests(TestCase):
2481 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002482 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002483 """
2484 def test_type(self):
2485 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002486 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002487 """
2488 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05002489 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05002490
2491
2492
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002493class ConstantsTests(TestCase):
2494 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002495 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002496
2497 These are values defined by OpenSSL intended only to be used as flags to
2498 OpenSSL APIs. The only assertions it seems can be made about them is
2499 their values.
2500 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002501 # unittest.TestCase has no skip mechanism
2502 if OP_NO_QUERY_MTU is not None:
2503 def test_op_no_query_mtu(self):
2504 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002505 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002506 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002507 """
2508 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
2509 else:
2510 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002511
2512
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002513 if OP_COOKIE_EXCHANGE is not None:
2514 def test_op_cookie_exchange(self):
2515 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002516 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002517 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002518 """
2519 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
2520 else:
2521 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002522
2523
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002524 if OP_NO_TICKET is not None:
2525 def test_op_no_ticket(self):
2526 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002527 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002528 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002529 """
2530 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04002531 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002532 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05002533
2534
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002535 if OP_NO_COMPRESSION is not None:
2536 def test_op_no_compression(self):
2537 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002538 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
2539 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002540 """
2541 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
2542 else:
2543 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
2544
2545
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002546 def test_sess_cache_off(self):
2547 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002548 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
2549 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002550 """
2551 self.assertEqual(0x0, SESS_CACHE_OFF)
2552
2553
2554 def test_sess_cache_client(self):
2555 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002556 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
2557 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002558 """
2559 self.assertEqual(0x1, SESS_CACHE_CLIENT)
2560
2561
2562 def test_sess_cache_server(self):
2563 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002564 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
2565 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002566 """
2567 self.assertEqual(0x2, SESS_CACHE_SERVER)
2568
2569
2570 def test_sess_cache_both(self):
2571 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002572 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
2573 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002574 """
2575 self.assertEqual(0x3, SESS_CACHE_BOTH)
2576
2577
2578 def test_sess_cache_no_auto_clear(self):
2579 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002580 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
2581 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
2582 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002583 """
2584 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
2585
2586
2587 def test_sess_cache_no_internal_lookup(self):
2588 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002589 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
2590 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
2591 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002592 """
2593 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
2594
2595
2596 def test_sess_cache_no_internal_store(self):
2597 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002598 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
2599 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
2600 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002601 """
2602 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
2603
2604
2605 def test_sess_cache_no_internal(self):
2606 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002607 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
2608 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
2609 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002610 """
2611 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
2612
2613
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04002614
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002615class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05002616 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002617 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05002618 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002619 def _server(self, sock):
2620 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002621 Create a new server-side SSL :py:obj:`Connection` object wrapped around
2622 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002623 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002624 # Create the server side Connection. This is mostly setup boilerplate
2625 # - use TLSv1, use a particular certificate, etc.
2626 server_ctx = Context(TLSv1_METHOD)
2627 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2628 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2629 server_store = server_ctx.get_cert_store()
2630 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2631 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2632 server_ctx.check_privatekey()
2633 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002634 # Here the Connection is actually created. If None is passed as the 2nd
2635 # parameter, it indicates a memory BIO should be created.
2636 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002637 server_conn.set_accept_state()
2638 return server_conn
2639
2640
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002641 def _client(self, sock):
2642 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002643 Create a new client-side SSL :py:obj:`Connection` object wrapped around
2644 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002645 """
2646 # Now create the client side Connection. Similar boilerplate to the
2647 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002648 client_ctx = Context(TLSv1_METHOD)
2649 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2650 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2651 client_store = client_ctx.get_cert_store()
2652 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
2653 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
2654 client_ctx.check_privatekey()
2655 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002656 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002657 client_conn.set_connect_state()
2658 return client_conn
2659
2660
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002661 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002662 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002663 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002664 reading from the output of each and writing those bytes to the input of
2665 the other and in this way establish a connection and exchange
2666 application-level bytes with each other.
2667 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002668 server_conn = self._server(None)
2669 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002670
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002671 # There should be no key or nonces yet.
2672 self.assertIdentical(server_conn.master_key(), None)
2673 self.assertIdentical(server_conn.client_random(), None)
2674 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002675
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002676 # First, the handshake needs to happen. We'll deliver bytes back and
2677 # forth between the client and server until neither of them feels like
2678 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002679 self.assertIdentical(
2680 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002681
2682 # Now that the handshake is done, there should be a key and nonces.
2683 self.assertNotIdentical(server_conn.master_key(), None)
2684 self.assertNotIdentical(server_conn.client_random(), None)
2685 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04002686 self.assertEquals(server_conn.client_random(), client_conn.client_random())
2687 self.assertEquals(server_conn.server_random(), client_conn.server_random())
2688 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
2689 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002690
2691 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002692 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05002693
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002694 server_conn.write(important_message)
2695 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002696 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002697 (client_conn, important_message))
2698
2699 client_conn.write(important_message[::-1])
2700 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002701 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002702 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05002703
2704
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002705 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05002706 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002707 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002708
2709 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09002710 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002711 this test fails, there must be a problem outside the memory BIO
2712 code, as no memory BIO is involved here). Even though this isn't a
2713 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05002714 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04002715 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05002716
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002717 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05002718 client_conn.send(important_message)
2719 msg = server_conn.recv(1024)
2720 self.assertEqual(msg, important_message)
2721
2722 # Again in the other direction, just for fun.
2723 important_message = important_message[::-1]
2724 server_conn.send(important_message)
2725 msg = client_conn.recv(1024)
2726 self.assertEqual(msg, important_message)
2727
2728
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04002729 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05002730 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002731 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
2732 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05002733 """
2734 context = Context(SSLv3_METHOD)
2735 client = socket()
2736 clientSSL = Connection(context, client)
2737 self.assertRaises( TypeError, clientSSL.bio_read, 100)
2738 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04002739 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002740
2741
2742 def test_outgoingOverflow(self):
2743 """
2744 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002745 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002746 returned and that many bytes from the beginning of the input can be
2747 read from the other end of the connection.
2748 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002749 server = self._server(None)
2750 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002751
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002752 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002753
2754 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002755 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002756 # Sanity check. We're trying to test what happens when the entire
2757 # input can't be sent. If the entire input was sent, this test is
2758 # meaningless.
2759 self.assertTrue(sent < size)
2760
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002761 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002762 self.assertIdentical(receiver, server)
2763
2764 # We can rely on all of these bytes being received at once because
2765 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
2766 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002767
2768
2769 def test_shutdown(self):
2770 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002771 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
2772 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002773 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002774 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002775 server.bio_shutdown()
2776 e = self.assertRaises(Error, server.recv, 1024)
2777 # We don't want WantReadError or ZeroReturnError or anything - it's a
2778 # handshake failure.
2779 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002780
2781
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002782 def test_unexpectedEndOfFile(self):
2783 """
2784 If the connection is lost before an orderly SSL shutdown occurs,
2785 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
2786 "Unexpected EOF".
2787 """
2788 server_conn, client_conn = self._loopback()
2789 client_conn.sock_shutdown(SHUT_RDWR)
2790 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
2791 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
2792
2793
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002794 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002795 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002796 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 -04002797
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002798 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002799 before the client and server are connected to each other. This
2800 function should specify a list of CAs for the server to send to the
2801 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09002802 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002803 times.
2804 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002805 server = self._server(None)
2806 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002807 self.assertEqual(client.get_client_ca_list(), [])
2808 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002809 ctx = server.get_context()
2810 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002811 self.assertEqual(client.get_client_ca_list(), [])
2812 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002813 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002814 self.assertEqual(client.get_client_ca_list(), expected)
2815 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002816
2817
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002818 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002819 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002820 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002821 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002822 """
2823 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002824 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
2825 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
2826 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002827
2828
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002829 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002830 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002831 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002832 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09002833 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002834 after the connection is set up.
2835 """
2836 def no_ca(ctx):
2837 ctx.set_client_ca_list([])
2838 return []
2839 self._check_client_ca_list(no_ca)
2840
2841
2842 def test_set_one_ca_list(self):
2843 """
2844 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002845 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002846 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002847 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002848 X509Name after the connection is set up.
2849 """
2850 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2851 cadesc = cacert.get_subject()
2852 def single_ca(ctx):
2853 ctx.set_client_ca_list([cadesc])
2854 return [cadesc]
2855 self._check_client_ca_list(single_ca)
2856
2857
2858 def test_set_multiple_ca_list(self):
2859 """
2860 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002861 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002862 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002863 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002864 X509Names after the connection is set up.
2865 """
2866 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2867 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2868
2869 sedesc = secert.get_subject()
2870 cldesc = clcert.get_subject()
2871
2872 def multiple_ca(ctx):
2873 L = [sedesc, cldesc]
2874 ctx.set_client_ca_list(L)
2875 return L
2876 self._check_client_ca_list(multiple_ca)
2877
2878
2879 def test_reset_ca_list(self):
2880 """
2881 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09002882 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002883 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002884 """
2885 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2886 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2887 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2888
2889 cadesc = cacert.get_subject()
2890 sedesc = secert.get_subject()
2891 cldesc = clcert.get_subject()
2892
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002893 def changed_ca(ctx):
2894 ctx.set_client_ca_list([sedesc, cldesc])
2895 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002896 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002897 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002898
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002899
2900 def test_mutated_ca_list(self):
2901 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002902 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002903 afterwards, this does not affect the list of CA names sent to the
2904 client.
2905 """
2906 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2907 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2908
2909 cadesc = cacert.get_subject()
2910 sedesc = secert.get_subject()
2911
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002912 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002913 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002914 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002915 L.append(sedesc)
2916 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002917 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002918
2919
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002920 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002921 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002922 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002923 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002924 """
2925 ctx = Context(TLSv1_METHOD)
2926 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002927 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002928 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002929 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002930
2931
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002932 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002933 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002934 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09002935 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002936 """
2937 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2938 cadesc = cacert.get_subject()
2939 def single_ca(ctx):
2940 ctx.add_client_ca(cacert)
2941 return [cadesc]
2942 self._check_client_ca_list(single_ca)
2943
2944
2945 def test_multiple_add_client_ca(self):
2946 """
2947 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09002948 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002949 """
2950 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2951 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2952
2953 cadesc = cacert.get_subject()
2954 sedesc = secert.get_subject()
2955
2956 def multiple_ca(ctx):
2957 ctx.add_client_ca(cacert)
2958 ctx.add_client_ca(secert)
2959 return [cadesc, sedesc]
2960 self._check_client_ca_list(multiple_ca)
2961
2962
2963 def test_set_and_add_client_ca(self):
2964 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002965 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
2966 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002967 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002968 """
2969 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2970 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2971 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2972
2973 cadesc = cacert.get_subject()
2974 sedesc = secert.get_subject()
2975 cldesc = clcert.get_subject()
2976
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002977 def mixed_set_add_ca(ctx):
2978 ctx.set_client_ca_list([cadesc, sedesc])
2979 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002980 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002981 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002982
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002983
2984 def test_set_after_add_client_ca(self):
2985 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002986 A call to :py:obj:`Context.set_client_ca_list` after a call to
2987 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002988 call with the names specified by the latter cal.
2989 """
2990 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2991 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2992 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2993
2994 cadesc = cacert.get_subject()
2995 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002996
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002997 def set_replaces_add_ca(ctx):
2998 ctx.add_client_ca(clcert)
2999 ctx.set_client_ca_list([cadesc])
3000 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003001 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003002 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003003
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003004
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003005
3006class ConnectionBIOTests(TestCase):
3007 """
3008 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3009 """
3010 def test_wantReadError(self):
3011 """
3012 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
3013 if there are no bytes available to be read from the BIO.
3014 """
3015 ctx = Context(TLSv1_METHOD)
3016 conn = Connection(ctx, None)
3017 self.assertRaises(WantReadError, conn.bio_read, 1024)
3018
3019
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003020 def test_buffer_size(self):
3021 """
3022 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3023 number of bytes to read and return.
3024 """
3025 ctx = Context(TLSv1_METHOD)
3026 conn = Connection(ctx, None)
3027 conn.set_connect_state()
3028 try:
3029 conn.do_handshake()
3030 except WantReadError:
3031 pass
3032 data = conn.bio_read(2)
3033 self.assertEqual(2, len(data))
3034
3035
3036 if not PY3:
3037 def test_buffer_size_long(self):
3038 """
3039 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3040 :py:obj:`long` as well as :py:obj:`int`.
3041 """
3042 ctx = Context(TLSv1_METHOD)
3043 conn = Connection(ctx, None)
3044 conn.set_connect_state()
3045 try:
3046 conn.do_handshake()
3047 except WantReadError:
3048 pass
3049 data = conn.bio_read(long(2))
3050 self.assertEqual(2, len(data))
3051
3052
3053
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003054
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003055class InfoConstantTests(TestCase):
3056 """
3057 Tests for assorted constants exposed for use in info callbacks.
3058 """
3059 def test_integers(self):
3060 """
3061 All of the info constants are integers.
3062
3063 This is a very weak test. It would be nice to have one that actually
3064 verifies that as certain info events happen, the value passed to the
3065 info callback matches up with the constant exposed by OpenSSL.SSL.
3066 """
3067 for const in [
3068 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3069 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3070 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3071 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3072 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
3073 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
3074
3075 self.assertTrue(isinstance(const, int))
3076
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003077
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003078if __name__ == '__main__':
3079 main()