blob: a77c86a825a411a52b990a738e21c72719b64282 [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
923 def test_load_verify_invalid_file(self):
924 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900925 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when passed a
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400926 non-existent cafile.
927 """
928 clientContext = Context(TLSv1_METHOD)
929 self.assertRaises(
930 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400931
932
933 def test_load_verify_directory(self):
934 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900935 :py:obj:`Context.load_verify_locations` accepts a directory name and uses
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400936 the certificates within for verification purposes.
937 """
938 capath = self.mktemp()
939 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400940 # Hash values computed manually with c_rehash to avoid depending on
941 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
942 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500943 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400944 cafile = join(capath, name)
945 fObj = open(cafile, 'w')
946 fObj.write(cleartextCertificatePEM.decode('ascii'))
947 fObj.close()
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400948
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400949 self._load_verify_locations_test(None, capath)
950
951
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400952 def test_load_verify_locations_wrong_args(self):
953 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900954 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if called with
955 the wrong number of arguments or with non-:py:obj:`str` arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400956 """
957 context = Context(TLSv1_METHOD)
958 self.assertRaises(TypeError, context.load_verify_locations)
959 self.assertRaises(TypeError, context.load_verify_locations, object())
960 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
961 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
962
963
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400964 if platform == "win32":
965 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400966 "See LP#404343 and LP#404344."
967 else:
968 def test_set_default_verify_paths(self):
969 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900970 :py:obj:`Context.set_default_verify_paths` causes the platform-specific CA
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400971 certificate locations to be used for verification purposes.
972 """
973 # Testing this requires a server with a certificate signed by one of
974 # the CAs in the platform CA location. Getting one of those costs
975 # money. Fortunately (or unfortunately, depending on your
976 # perspective), it's easy to think of a public server on the
977 # internet which has such a certificate. Connecting to the network
978 # in a unit test is bad, but it's the only way I can think of to
979 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400980
Alex Gaynorb586da32014-11-15 09:22:21 -0800981 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
982 context = Context(TLSv1_METHOD)
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400983 context.set_default_verify_paths()
984 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +0200985 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400986 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400987
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400988 client = socket()
989 client.connect(('verisign.com', 443))
990 clientSSL = Connection(context, client)
991 clientSSL.set_connect_state()
992 clientSSL.do_handshake()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500993 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400994 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400995
996
997 def test_set_default_verify_paths_signature(self):
998 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900999 :py:obj:`Context.set_default_verify_paths` takes no arguments and raises
1000 :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001001 """
1002 context = Context(TLSv1_METHOD)
1003 self.assertRaises(TypeError, context.set_default_verify_paths, None)
1004 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
1005 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001006
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001007
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001008 def test_add_extra_chain_cert_invalid_cert(self):
1009 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001010 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if called with
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001011 other than one argument or if called with an object which is not an
Jonathan Ballet648875f2011-07-16 14:14:58 +09001012 instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001013 """
1014 context = Context(TLSv1_METHOD)
1015 self.assertRaises(TypeError, context.add_extra_chain_cert)
1016 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
1017 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
1018
1019
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001020 def _handshake_test(self, serverContext, clientContext):
1021 """
1022 Verify that a client and server created with the given contexts can
1023 successfully handshake and communicate.
1024 """
1025 serverSocket, clientSocket = socket_pair()
1026
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001027 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001028 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001029
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001030 client = Connection(clientContext, clientSocket)
1031 client.set_connect_state()
1032
1033 # Make them talk to each other.
1034 # self._interactInMemory(client, server)
1035 for i in range(3):
1036 for s in [client, server]:
1037 try:
1038 s.do_handshake()
1039 except WantReadError:
1040 pass
1041
1042
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001043 def test_set_verify_callback_connection_argument(self):
1044 """
1045 The first argument passed to the verify callback is the
1046 :py:class:`Connection` instance for which verification is taking place.
1047 """
1048 serverContext = Context(TLSv1_METHOD)
1049 serverContext.use_privatekey(
1050 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1051 serverContext.use_certificate(
1052 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1053 serverConnection = Connection(serverContext, None)
1054
1055 class VerifyCallback(object):
1056 def callback(self, connection, *args):
1057 self.connection = connection
1058 return 1
1059
1060 verify = VerifyCallback()
1061 clientContext = Context(TLSv1_METHOD)
1062 clientContext.set_verify(VERIFY_PEER, verify.callback)
1063 clientConnection = Connection(clientContext, None)
1064 clientConnection.set_connect_state()
1065
1066 self._handshakeInMemory(clientConnection, serverConnection)
1067
1068 self.assertIdentical(verify.connection, clientConnection)
1069
1070
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001071 def test_set_verify_callback_exception(self):
1072 """
1073 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1074 exception, verification fails and the exception is propagated to the
1075 caller of :py:obj:`Connection.do_handshake`.
1076 """
1077 serverContext = Context(TLSv1_METHOD)
1078 serverContext.use_privatekey(
1079 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1080 serverContext.use_certificate(
1081 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1082
1083 clientContext = Context(TLSv1_METHOD)
1084 def verify_callback(*args):
1085 raise Exception("silly verify failure")
1086 clientContext.set_verify(VERIFY_PEER, verify_callback)
1087
1088 exc = self.assertRaises(
1089 Exception, self._handshake_test, serverContext, clientContext)
1090 self.assertEqual("silly verify failure", str(exc))
1091
1092
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001093 def test_add_extra_chain_cert(self):
1094 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001095 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509` instance to add to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001096 the certificate chain.
1097
Jonathan Ballet648875f2011-07-16 14:14:58 +09001098 See :py:obj:`_create_certificate_chain` for the details of the certificate
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001099 chain tested.
1100
1101 The chain is tested by starting a server with scert and connecting
1102 to it with a client which trusts cacert and requires verification to
1103 succeed.
1104 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001105 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001106 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1107
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001108 # Dump the CA certificate to a file because that's the only way to load
1109 # it as a trusted CA in the client context.
1110 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001111 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001112 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001113 fObj.close()
1114
1115 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001116 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001117 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001118 fObj.close()
1119
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001120 # Create the server context
1121 serverContext = Context(TLSv1_METHOD)
1122 serverContext.use_privatekey(skey)
1123 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001124 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001125 serverContext.add_extra_chain_cert(icert)
1126
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001127 # Create the client
1128 clientContext = Context(TLSv1_METHOD)
1129 clientContext.set_verify(
1130 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001131 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001132
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001133 # Try it out.
1134 self._handshake_test(serverContext, clientContext)
1135
1136
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001137 def test_use_certificate_chain_file(self):
1138 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001139 :py:obj:`Context.use_certificate_chain_file` reads a certificate chain from
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001140 the specified file.
1141
1142 The chain is tested by starting a server with scert and connecting
1143 to it with a client which trusts cacert and requires verification to
1144 succeed.
1145 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001146 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001147 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1148
1149 # Write out the chain file.
1150 chainFile = self.mktemp()
Jean-Paul Calderoned8607982014-01-18 10:30:55 -05001151 fObj = open(chainFile, 'wb')
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001152 # Most specific to least general.
Jean-Paul Calderoned8607982014-01-18 10:30:55 -05001153 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1154 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1155 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001156 fObj.close()
1157
1158 serverContext = Context(TLSv1_METHOD)
1159 serverContext.use_certificate_chain_file(chainFile)
1160 serverContext.use_privatekey(skey)
1161
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001162 fObj = open('ca.pem', 'w')
1163 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001164 fObj.close()
1165
1166 clientContext = Context(TLSv1_METHOD)
1167 clientContext.set_verify(
1168 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001169 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001170
1171 self._handshake_test(serverContext, clientContext)
1172
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001173
1174 def test_use_certificate_chain_file_wrong_args(self):
1175 """
1176 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1177 if passed zero or more than one argument or when passed a non-byte
1178 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error` when
1179 passed a bad chain file name (for example, the name of a file which does
1180 not exist).
1181 """
1182 context = Context(TLSv1_METHOD)
1183 self.assertRaises(TypeError, context.use_certificate_chain_file)
1184 self.assertRaises(TypeError, context.use_certificate_chain_file, object())
1185 self.assertRaises(TypeError, context.use_certificate_chain_file, b"foo", object())
1186
1187 self.assertRaises(Error, context.use_certificate_chain_file, self.mktemp())
1188
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001189 # XXX load_client_ca
1190 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001191
1192 def test_get_verify_mode_wrong_args(self):
1193 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001194 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001195 arguments.
1196 """
1197 context = Context(TLSv1_METHOD)
1198 self.assertRaises(TypeError, context.get_verify_mode, None)
1199
1200
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001201 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001202 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001203 :py:obj:`Context.get_verify_mode` returns the verify mode flags previously
1204 passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001205 """
1206 context = Context(TLSv1_METHOD)
1207 self.assertEquals(context.get_verify_mode(), 0)
1208 context.set_verify(
1209 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1210 self.assertEquals(
1211 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1212
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001213
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001214 if not PY3:
1215 def test_set_verify_mode_long(self):
1216 """
1217 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1218 type :py:obj:`long` as well as :py:obj:`int`.
1219 """
1220 context = Context(TLSv1_METHOD)
1221 self.assertEquals(context.get_verify_mode(), 0)
1222 context.set_verify(
1223 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None)
1224 self.assertEquals(
1225 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1226
1227
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001228 def test_load_tmp_dh_wrong_args(self):
1229 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001230 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
1231 number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001232 """
1233 context = Context(TLSv1_METHOD)
1234 self.assertRaises(TypeError, context.load_tmp_dh)
1235 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1236 self.assertRaises(TypeError, context.load_tmp_dh, object())
1237
1238
1239 def test_load_tmp_dh_missing_file(self):
1240 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001241 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the specified file
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001242 does not exist.
1243 """
1244 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001245 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001246
1247
1248 def test_load_tmp_dh(self):
1249 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001250 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001251 specified file.
1252 """
1253 context = Context(TLSv1_METHOD)
1254 dhfilename = self.mktemp()
1255 dhfile = open(dhfilename, "w")
1256 dhfile.write(dhparam)
1257 dhfile.close()
1258 context.load_tmp_dh(dhfilename)
1259 # XXX What should I assert here? -exarkun
1260
1261
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001262 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001263 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001264 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001265 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001266 """
1267 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001268 for curve in get_elliptic_curves():
1269 # The only easily "assertable" thing is that it does not raise an
1270 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001271 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001272
1273
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001274 def test_set_cipher_list_bytes(self):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001275 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001276 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
1277 ciphers which connections created with the context object will be able
1278 to choose from.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001279 """
1280 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001281 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001282 conn = Connection(context, None)
1283 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001284
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001285
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001286 def test_set_cipher_list_text(self):
1287 """
1288 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
1289 the ciphers which connections created with the context object will be
1290 able to choose from.
1291 """
1292 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -05001293 context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001294 conn = Connection(context, None)
1295 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
1296
1297
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001298 def test_set_cipher_list_wrong_args(self):
1299 """
Jean-Paul Calderone17044832014-01-18 10:20:11 -05001300 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
1301 passed zero arguments or more than one argument or when passed a
1302 non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001303 passed an incorrect cipher list string.
1304 """
1305 context = Context(TLSv1_METHOD)
1306 self.assertRaises(TypeError, context.set_cipher_list)
1307 self.assertRaises(TypeError, context.set_cipher_list, object())
1308 self.assertRaises(TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object())
1309
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001310 self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001311
1312
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001313 def test_set_session_cache_mode_wrong_args(self):
1314 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001315 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1316 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001317 """
1318 context = Context(TLSv1_METHOD)
1319 self.assertRaises(TypeError, context.set_session_cache_mode)
1320 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1321
1322
1323 def test_get_session_cache_mode_wrong_args(self):
1324 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001325 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1326 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001327 """
1328 context = Context(TLSv1_METHOD)
1329 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1330
1331
1332 def test_session_cache_mode(self):
1333 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001334 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1335 cached. The setting can be retrieved via
1336 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001337 """
1338 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001339 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001340 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1341 self.assertEqual(SESS_CACHE_OFF, off)
1342 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1343
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001344 if not PY3:
1345 def test_session_cache_mode_long(self):
1346 """
1347 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1348 of type :py:obj:`long` as well as :py:obj:`int`.
1349 """
1350 context = Context(TLSv1_METHOD)
1351 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1352 self.assertEqual(
1353 SESS_CACHE_BOTH, context.get_session_cache_mode())
1354
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001355
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001356 def test_get_cert_store(self):
1357 """
1358 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store` instance.
1359 """
1360 context = Context(TLSv1_METHOD)
1361 store = context.get_cert_store()
1362 self.assertIsInstance(store, X509Store)
1363
1364
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001365
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001366class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1367 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001368 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
1369 :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001370 """
1371 def test_wrong_args(self):
1372 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001373 :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001374 with other than one argument.
1375 """
1376 context = Context(TLSv1_METHOD)
1377 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1378 self.assertRaises(
1379 TypeError, context.set_tlsext_servername_callback, 1, 2)
1380
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001381
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001382 def test_old_callback_forgotten(self):
1383 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001384 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001385 callback, the one it replaces is dereferenced.
1386 """
1387 def callback(connection):
1388 pass
1389
1390 def replacement(connection):
1391 pass
1392
1393 context = Context(TLSv1_METHOD)
1394 context.set_tlsext_servername_callback(callback)
1395
1396 tracker = ref(callback)
1397 del callback
1398
1399 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001400
1401 # One run of the garbage collector happens to work on CPython. PyPy
1402 # doesn't collect the underlying object until a second run for whatever
1403 # reason. That's fine, it still demonstrates our code has properly
1404 # dropped the reference.
1405 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001406 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001407
1408 callback = tracker()
1409 if callback is not None:
1410 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001411 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001412 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001413
1414
1415 def test_no_servername(self):
1416 """
1417 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001418 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
1419 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001420 """
1421 args = []
1422 def servername(conn):
1423 args.append((conn, conn.get_servername()))
1424 context = Context(TLSv1_METHOD)
1425 context.set_tlsext_servername_callback(servername)
1426
1427 # Lose our reference to it. The Context is responsible for keeping it
1428 # alive now.
1429 del servername
1430 collect()
1431
1432 # Necessary to actually accept the connection
1433 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1434 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1435
1436 # Do a little connection to trigger the logic
1437 server = Connection(context, None)
1438 server.set_accept_state()
1439
1440 client = Connection(Context(TLSv1_METHOD), None)
1441 client.set_connect_state()
1442
1443 self._interactInMemory(server, client)
1444
1445 self.assertEqual([(server, None)], args)
1446
1447
1448 def test_servername(self):
1449 """
1450 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +09001451 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
1452 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001453 """
1454 args = []
1455 def servername(conn):
1456 args.append((conn, conn.get_servername()))
1457 context = Context(TLSv1_METHOD)
1458 context.set_tlsext_servername_callback(servername)
1459
1460 # Necessary to actually accept the connection
1461 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1462 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1463
1464 # Do a little connection to trigger the logic
1465 server = Connection(context, None)
1466 server.set_accept_state()
1467
1468 client = Connection(Context(TLSv1_METHOD), None)
1469 client.set_connect_state()
1470 client.set_tlsext_host_name(b("foo1.example.com"))
1471
1472 self._interactInMemory(server, client)
1473
1474 self.assertEqual([(server, b("foo1.example.com"))], args)
1475
1476
1477
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001478class SessionTests(TestCase):
1479 """
1480 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1481 """
1482 def test_construction(self):
1483 """
1484 :py:class:`Session` can be constructed with no arguments, creating a new
1485 instance of that type.
1486 """
1487 new_session = Session()
1488 self.assertTrue(isinstance(new_session, Session))
1489
1490
1491 def test_construction_wrong_args(self):
1492 """
1493 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
1494 is raised.
1495 """
1496 self.assertRaises(TypeError, Session, 123)
1497 self.assertRaises(TypeError, Session, "hello")
1498 self.assertRaises(TypeError, Session, object())
1499
1500
1501
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001502class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05001503 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001504 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001505 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001506 # XXX get_peer_certificate -> None
1507 # XXX sock_shutdown
1508 # XXX master_key -> TypeError
1509 # XXX server_random -> TypeError
1510 # XXX state_string
1511 # XXX connect -> TypeError
1512 # XXX connect_ex -> TypeError
1513 # XXX set_connect_state -> TypeError
1514 # XXX set_accept_state -> TypeError
1515 # XXX renegotiate_pending
1516 # XXX do_handshake -> TypeError
1517 # XXX bio_read -> TypeError
1518 # XXX recv -> TypeError
1519 # XXX send -> TypeError
1520 # XXX bio_write -> TypeError
1521
Rick Deane15b1472009-07-09 15:53:42 -05001522 def test_type(self):
1523 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001524 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001525 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05001526 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001527 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05001528 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001529 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05001530
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001531
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001532 def test_get_context(self):
1533 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001534 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
1535 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001536 """
1537 context = Context(TLSv1_METHOD)
1538 connection = Connection(context, None)
1539 self.assertIdentical(connection.get_context(), context)
1540
1541
1542 def test_get_context_wrong_args(self):
1543 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001544 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001545 arguments.
1546 """
1547 connection = Connection(Context(TLSv1_METHOD), None)
1548 self.assertRaises(TypeError, connection.get_context, None)
1549
1550
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001551 def test_set_context_wrong_args(self):
1552 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001553 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
1554 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001555 than 1.
1556 """
1557 ctx = Context(TLSv1_METHOD)
1558 connection = Connection(ctx, None)
1559 self.assertRaises(TypeError, connection.set_context)
1560 self.assertRaises(TypeError, connection.set_context, object())
1561 self.assertRaises(TypeError, connection.set_context, "hello")
1562 self.assertRaises(TypeError, connection.set_context, 1)
1563 self.assertRaises(TypeError, connection.set_context, 1, 2)
1564 self.assertRaises(
1565 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
1566 self.assertIdentical(ctx, connection.get_context())
1567
1568
1569 def test_set_context(self):
1570 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001571 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001572 for the connection.
1573 """
1574 original = Context(SSLv23_METHOD)
1575 replacement = Context(TLSv1_METHOD)
1576 connection = Connection(original, None)
1577 connection.set_context(replacement)
1578 self.assertIdentical(replacement, connection.get_context())
1579 # Lose our references to the contexts, just in case the Connection isn't
1580 # properly managing its own contributions to their reference counts.
1581 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001582 collect()
1583
1584
1585 def test_set_tlsext_host_name_wrong_args(self):
1586 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001587 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001588 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09001589 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001590 """
1591 conn = Connection(Context(TLSv1_METHOD), None)
1592 self.assertRaises(TypeError, conn.set_tlsext_host_name)
1593 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
1594 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
1595 self.assertRaises(
1596 TypeError, conn.set_tlsext_host_name, b("with\0null"))
1597
Abraham Martinc5484ba2015-03-25 15:33:05 +00001598 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001599 # On Python 3.x, don't accidentally implicitly convert from text.
1600 self.assertRaises(
1601 TypeError,
1602 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001603
1604
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001605 def test_get_servername_wrong_args(self):
1606 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001607 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001608 arguments.
1609 """
1610 connection = Connection(Context(TLSv1_METHOD), None)
1611 self.assertRaises(TypeError, connection.get_servername, object())
1612 self.assertRaises(TypeError, connection.get_servername, 1)
1613 self.assertRaises(TypeError, connection.get_servername, "hello")
1614
1615
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001616 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001617 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001618 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001619 immediate read.
1620 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001621 connection = Connection(Context(TLSv1_METHOD), None)
1622 self.assertEquals(connection.pending(), 0)
1623
1624
1625 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001626 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001627 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001628 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001629 connection = Connection(Context(TLSv1_METHOD), None)
1630 self.assertRaises(TypeError, connection.pending, None)
1631
1632
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001633 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001634 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001635 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001636 argument or with the wrong number of arguments.
1637 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001638 connection = Connection(Context(TLSv1_METHOD), socket())
1639 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001640 self.assertRaises(TypeError, connection.connect)
1641 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001642
1643
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001644 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001645 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001646 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001647 connect method raises it.
1648 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001649 client = socket()
1650 context = Context(TLSv1_METHOD)
1651 clientSSL = Connection(context, client)
1652 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04001653 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001654
1655
1656 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001657 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001658 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001659 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001660 port = socket()
1661 port.bind(('', 0))
1662 port.listen(3)
1663
1664 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001665 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
1666 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001667
1668
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001669 if platform == "darwin":
1670 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
1671 else:
1672 def test_connect_ex(self):
1673 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001674 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001675 errno instead of raising an exception.
1676 """
1677 port = socket()
1678 port.bind(('', 0))
1679 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001680
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001681 clientSSL = Connection(Context(TLSv1_METHOD), socket())
1682 clientSSL.setblocking(False)
1683 result = clientSSL.connect_ex(port.getsockname())
1684 expected = (EINPROGRESS, EWOULDBLOCK)
1685 self.assertTrue(
1686 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001687
1688
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001689 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001690 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001691 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001692 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001693 connection = Connection(Context(TLSv1_METHOD), socket())
1694 self.assertRaises(TypeError, connection.accept, None)
1695
1696
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001697 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001698 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001699 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
1700 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001701 connection originated from.
1702 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001703 ctx = Context(TLSv1_METHOD)
1704 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1705 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001706 port = socket()
1707 portSSL = Connection(ctx, port)
1708 portSSL.bind(('', 0))
1709 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001710
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001711 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001712
1713 # Calling portSSL.getsockname() here to get the server IP address sounds
1714 # great, but frequently fails on Windows.
1715 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001716
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001717 serverSSL, address = portSSL.accept()
1718
1719 self.assertTrue(isinstance(serverSSL, Connection))
1720 self.assertIdentical(serverSSL.get_context(), ctx)
1721 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001722
1723
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001724 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001725 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001726 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001727 number of arguments or with arguments other than integers.
1728 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001729 connection = Connection(Context(TLSv1_METHOD), None)
1730 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04001731 self.assertRaises(TypeError, connection.get_shutdown, None)
1732 self.assertRaises(TypeError, connection.set_shutdown)
1733 self.assertRaises(TypeError, connection.set_shutdown, None)
1734 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001735
1736
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001737 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001738 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001739 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001740 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001741 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001742 self.assertFalse(server.shutdown())
1743 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001744 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001745 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
1746 client.shutdown()
1747 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
1748 self.assertRaises(ZeroReturnError, server.recv, 1024)
1749 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001750
1751
Paul Aurichc85e0862015-01-08 08:34:33 -08001752 def test_shutdown_closed(self):
1753 """
1754 If the underlying socket is closed, :py:obj:`Connection.shutdown` propagates the
1755 write error from the low level write call.
1756 """
1757 server, client = self._loopback()
1758 server.sock_shutdown(2)
1759 exc = self.assertRaises(SysCallError, server.shutdown)
1760 if platform == "win32":
1761 self.assertEqual(exc.args[0], ESHUTDOWN)
1762 else:
1763 self.assertEqual(exc.args[0], EPIPE)
1764
1765
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001766 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001767 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001768 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001769 process.
1770 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001771 connection = Connection(Context(TLSv1_METHOD), socket())
1772 connection.set_shutdown(RECEIVED_SHUTDOWN)
1773 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1774
1775
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05001776 if not PY3:
1777 def test_set_shutdown_long(self):
1778 """
1779 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
1780 of type :py:obj:`long` as well as :py:obj:`int`.
1781 """
1782 connection = Connection(Context(TLSv1_METHOD), socket())
1783 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
1784 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1785
1786
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001787 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001788 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001789 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
1790 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001791 with any arguments.
1792 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001793 conn = Connection(Context(TLSv1_METHOD), None)
1794 self.assertRaises(TypeError, conn.get_app_data, None)
1795 self.assertRaises(TypeError, conn.set_app_data)
1796 self.assertRaises(TypeError, conn.set_app_data, None, None)
1797
1798
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001799 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001800 """
1801 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001802 :py:obj:`Connection.set_app_data` and later retrieved with
1803 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001804 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001805 conn = Connection(Context(TLSv1_METHOD), None)
1806 app_data = object()
1807 conn.set_app_data(app_data)
1808 self.assertIdentical(conn.get_app_data(), app_data)
1809
1810
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001811 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001812 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001813 :py:obj:`Connection.makefile` is not implemented and calling that method raises
1814 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001815 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001816 conn = Connection(Context(TLSv1_METHOD), None)
1817 self.assertRaises(NotImplementedError, conn.makefile)
1818
1819
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001820 def test_get_peer_cert_chain_wrong_args(self):
1821 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001822 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001823 arguments.
1824 """
1825 conn = Connection(Context(TLSv1_METHOD), None)
1826 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
1827 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
1828 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
1829 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
1830
1831
1832 def test_get_peer_cert_chain(self):
1833 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001834 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001835 the connected server returned for the certification verification.
1836 """
1837 chain = _create_certificate_chain()
1838 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1839
1840 serverContext = Context(TLSv1_METHOD)
1841 serverContext.use_privatekey(skey)
1842 serverContext.use_certificate(scert)
1843 serverContext.add_extra_chain_cert(icert)
1844 serverContext.add_extra_chain_cert(cacert)
1845 server = Connection(serverContext, None)
1846 server.set_accept_state()
1847
1848 # Create the client
1849 clientContext = Context(TLSv1_METHOD)
1850 clientContext.set_verify(VERIFY_NONE, verify_cb)
1851 client = Connection(clientContext, None)
1852 client.set_connect_state()
1853
1854 self._interactInMemory(client, server)
1855
1856 chain = client.get_peer_cert_chain()
1857 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001858 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001859 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001860 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001861 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001862 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001863 "Authority Certificate", chain[2].get_subject().CN)
1864
1865
1866 def test_get_peer_cert_chain_none(self):
1867 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001868 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001869 certificate chain.
1870 """
1871 ctx = Context(TLSv1_METHOD)
1872 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1873 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1874 server = Connection(ctx, None)
1875 server.set_accept_state()
1876 client = Connection(Context(TLSv1_METHOD), None)
1877 client.set_connect_state()
1878 self._interactInMemory(client, server)
1879 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001880
1881
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001882 def test_get_session_wrong_args(self):
1883 """
1884 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
1885 with any arguments.
1886 """
1887 ctx = Context(TLSv1_METHOD)
1888 server = Connection(ctx, None)
1889 self.assertRaises(TypeError, server.get_session, 123)
1890 self.assertRaises(TypeError, server.get_session, "hello")
1891 self.assertRaises(TypeError, server.get_session, object())
1892
1893
1894 def test_get_session_unconnected(self):
1895 """
1896 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
1897 an object which has not been connected.
1898 """
1899 ctx = Context(TLSv1_METHOD)
1900 server = Connection(ctx, None)
1901 session = server.get_session()
1902 self.assertIdentical(None, session)
1903
1904
1905 def test_server_get_session(self):
1906 """
1907 On the server side of a connection, :py:obj:`Connection.get_session`
1908 returns a :py:class:`Session` instance representing the SSL session for
1909 that connection.
1910 """
1911 server, client = self._loopback()
1912 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001913 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001914
1915
1916 def test_client_get_session(self):
1917 """
1918 On the client side of a connection, :py:obj:`Connection.get_session`
1919 returns a :py:class:`Session` instance representing the SSL session for
1920 that connection.
1921 """
1922 server, client = self._loopback()
1923 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001924 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001925
1926
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05001927 def test_set_session_wrong_args(self):
1928 """
1929 If called with an object that is not an instance of :py:class:`Session`,
1930 or with other than one argument, :py:obj:`Connection.set_session` raises
1931 :py:obj:`TypeError`.
1932 """
1933 ctx = Context(TLSv1_METHOD)
1934 connection = Connection(ctx, None)
1935 self.assertRaises(TypeError, connection.set_session)
1936 self.assertRaises(TypeError, connection.set_session, 123)
1937 self.assertRaises(TypeError, connection.set_session, "hello")
1938 self.assertRaises(TypeError, connection.set_session, object())
1939 self.assertRaises(
1940 TypeError, connection.set_session, Session(), Session())
1941
1942
1943 def test_client_set_session(self):
1944 """
1945 :py:obj:`Connection.set_session`, when used prior to a connection being
1946 established, accepts a :py:class:`Session` instance and causes an
1947 attempt to re-use the session it represents when the SSL handshake is
1948 performed.
1949 """
1950 key = load_privatekey(FILETYPE_PEM, server_key_pem)
1951 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
1952 ctx = Context(TLSv1_METHOD)
1953 ctx.use_privatekey(key)
1954 ctx.use_certificate(cert)
1955 ctx.set_session_id("unity-test")
1956
1957 def makeServer(socket):
1958 server = Connection(ctx, socket)
1959 server.set_accept_state()
1960 return server
1961
1962 originalServer, originalClient = self._loopback(
1963 serverFactory=makeServer)
1964 originalSession = originalClient.get_session()
1965
1966 def makeClient(socket):
1967 client = self._loopbackClientFactory(socket)
1968 client.set_session(originalSession)
1969 return client
1970 resumedServer, resumedClient = self._loopback(
1971 serverFactory=makeServer,
1972 clientFactory=makeClient)
1973
1974 # This is a proxy: in general, we have no access to any unique
1975 # identifier for the session (new enough versions of OpenSSL expose a
1976 # hash which could be usable, but "new enough" is very, very new).
1977 # Instead, exploit the fact that the master key is re-used if the
1978 # session is re-used. As long as the master key for the two connections
1979 # is the same, the session was re-used!
1980 self.assertEqual(
1981 originalServer.master_key(), resumedServer.master_key())
1982
1983
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05001984 def test_set_session_wrong_method(self):
1985 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05001986 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
1987 instance associated with a context using a different SSL method than the
1988 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
1989 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05001990 """
1991 key = load_privatekey(FILETYPE_PEM, server_key_pem)
1992 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
1993 ctx = Context(TLSv1_METHOD)
1994 ctx.use_privatekey(key)
1995 ctx.use_certificate(cert)
1996 ctx.set_session_id("unity-test")
1997
1998 def makeServer(socket):
1999 server = Connection(ctx, socket)
2000 server.set_accept_state()
2001 return server
2002
2003 originalServer, originalClient = self._loopback(
2004 serverFactory=makeServer)
2005 originalSession = originalClient.get_session()
2006
2007 def makeClient(socket):
2008 # Intentionally use a different, incompatible method here.
2009 client = Connection(Context(SSLv3_METHOD), socket)
2010 client.set_connect_state()
2011 client.set_session(originalSession)
2012 return client
2013
2014 self.assertRaises(
2015 Error,
2016 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2017
2018
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002019 def test_wantWriteError(self):
2020 """
2021 :py:obj:`Connection` methods which generate output raise
2022 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2023 fail indicating a should-write state.
2024 """
2025 client_socket, server_socket = socket_pair()
2026 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002027 # anything. Only write a single byte at a time so we can be sure we
2028 # completely fill the buffer. Even though the socket API is allowed to
2029 # signal a short write via its return value it seems this doesn't
2030 # always happen on all platforms (FreeBSD and OS X particular) for the
2031 # very last bit of available buffer space.
2032 msg = b"x"
2033 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002034 try:
2035 client_socket.send(msg)
2036 except error as e:
2037 if e.errno == EWOULDBLOCK:
2038 break
2039 raise
2040 else:
2041 self.fail(
2042 "Failed to fill socket buffer, cannot test BIO want write")
2043
2044 ctx = Context(TLSv1_METHOD)
2045 conn = Connection(ctx, client_socket)
2046 # Client's speak first, so make it an SSL client
2047 conn.set_connect_state()
2048 self.assertRaises(WantWriteError, conn.do_handshake)
2049
2050 # XXX want_read
2051
Fedor Brunner416f4a12014-03-28 13:18:38 +01002052 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002053 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002054 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2055 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002056 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002057 ctx = Context(TLSv1_METHOD)
2058 connection = Connection(ctx, None)
2059 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002060
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002061
Fedor Brunner416f4a12014-03-28 13:18:38 +01002062 def test_get_peer_finished_before_connect(self):
2063 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002064 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2065 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002066 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002067 ctx = Context(TLSv1_METHOD)
2068 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002069 self.assertEqual(connection.get_peer_finished(), None)
2070
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002071
Fedor Brunner416f4a12014-03-28 13:18:38 +01002072 def test_get_finished(self):
2073 """
2074 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002075 message send from client, or server. Finished messages are send during
2076 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002077 """
2078
Fedor Brunner5747b932014-03-05 14:22:34 +01002079 server, client = self._loopback()
2080
2081 self.assertNotEqual(server.get_finished(), None)
2082 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002083
Jean-Paul Calderoned979f232014-03-30 11:58:00 -04002084
Fedor Brunner416f4a12014-03-28 13:18:38 +01002085 def test_get_peer_finished(self):
2086 """
2087 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002088 message received from client, or server. Finished messages are send
2089 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002090 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002091 server, client = self._loopback()
2092
2093 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002094 self.assertTrue(len(server.get_peer_finished()) > 0)
2095
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002096
Fedor Brunner416f4a12014-03-28 13:18:38 +01002097 def test_tls_finished_message_symmetry(self):
2098 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002099 The TLS Finished message send by server must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002100 received by client.
2101
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002102 The TLS Finished message send by client must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002103 received by server.
2104 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002105 server, client = self._loopback()
2106
Fedor Brunner5747b932014-03-05 14:22:34 +01002107 self.assertEqual(server.get_finished(), client.get_peer_finished())
2108 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002109
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002110
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002111 def test_get_cipher_name_before_connect(self):
2112 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002113 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2114 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002115 """
2116 ctx = Context(TLSv1_METHOD)
2117 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002118 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002119
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002120
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002121 def test_get_cipher_name(self):
2122 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002123 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2124 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002125 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002126 server, client = self._loopback()
2127 server_cipher_name, client_cipher_name = \
2128 server.get_cipher_name(), client.get_cipher_name()
2129
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002130 self.assertIsInstance(server_cipher_name, text_type)
2131 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002132
2133 self.assertEqual(server_cipher_name, client_cipher_name)
2134
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002135
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002136 def test_get_cipher_version_before_connect(self):
2137 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002138 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2139 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002140 """
2141 ctx = Context(TLSv1_METHOD)
2142 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002143 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002144
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002145
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002146 def test_get_cipher_version(self):
2147 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002148 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2149 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002150 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002151 server, client = self._loopback()
2152 server_cipher_version, client_cipher_version = \
2153 server.get_cipher_version(), client.get_cipher_version()
2154
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002155 self.assertIsInstance(server_cipher_version, text_type)
2156 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002157
2158 self.assertEqual(server_cipher_version, client_cipher_version)
2159
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002160
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002161 def test_get_cipher_bits_before_connect(self):
2162 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002163 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2164 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002165 """
2166 ctx = Context(TLSv1_METHOD)
2167 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002168 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002169
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002170
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002171 def test_get_cipher_bits(self):
2172 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002173 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2174 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002175 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002176 server, client = self._loopback()
2177 server_cipher_bits, client_cipher_bits = \
2178 server.get_cipher_bits(), client.get_cipher_bits()
2179
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002180 self.assertIsInstance(server_cipher_bits, int)
2181 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002182
2183 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002184
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002185
2186
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002187class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002188 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002189 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002190 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002191 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002192 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002193 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002194 arguments.
2195 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002196 connection = Connection(Context(TLSv1_METHOD), None)
2197 self.assertRaises(TypeError, connection.get_cipher_list, None)
2198
2199
2200 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002201 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002202 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2203 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002204 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002205 connection = Connection(Context(TLSv1_METHOD), None)
2206 ciphers = connection.get_cipher_list()
2207 self.assertTrue(isinstance(ciphers, list))
2208 for cipher in ciphers:
2209 self.assertTrue(isinstance(cipher, str))
2210
2211
2212
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002213class ConnectionSendTests(TestCase, _LoopbackMixin):
2214 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002215 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002216 """
2217 def test_wrong_args(self):
2218 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002219 When called with arguments other than string argument for its first
2220 parameter or more than two arguments, :py:obj:`Connection.send` raises
2221 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002222 """
2223 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002224 self.assertRaises(TypeError, connection.send)
2225 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002226 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002227
2228
2229 def test_short_bytes(self):
2230 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002231 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002232 and returns the number of bytes sent.
2233 """
2234 server, client = self._loopback()
2235 count = server.send(b('xy'))
2236 self.assertEquals(count, 2)
2237 self.assertEquals(client.recv(2), b('xy'))
2238
Abraham Martinef063482015-03-25 14:06:24 +00002239
2240 def test_text(self):
2241 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002242 When passed a text, :py:obj:`Connection.send` transmits all of it and
2243 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002244 """
2245 server, client = self._loopback()
2246 with catch_warnings(record=True) as w:
2247 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002248 count = server.send(b"xy".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002249 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002250 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002251 WARNING_TYPE_EXPECTED
2252 ),
2253 str(w[-1].message)
2254 )
2255 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinef063482015-03-25 14:06:24 +00002256 self.assertEquals(count, 2)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002257 self.assertEquals(client.recv(2), b"xy")
Abraham Martinef063482015-03-25 14:06:24 +00002258
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002259 try:
2260 memoryview
2261 except NameError:
2262 "cannot test sending memoryview without memoryview"
2263 else:
2264 def test_short_memoryview(self):
2265 """
2266 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002267 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002268 bytes sent.
2269 """
2270 server, client = self._loopback()
2271 count = server.send(memoryview(b('xy')))
2272 self.assertEquals(count, 2)
2273 self.assertEquals(client.recv(2), b('xy'))
2274
2275
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002276 try:
2277 buffer
2278 except NameError:
2279 "cannot test sending buffer without buffer"
2280 else:
2281 def test_short_buffer(self):
2282 """
2283 When passed a buffer containing a small number of bytes,
2284 :py:obj:`Connection.send` transmits all of them and returns the number of
2285 bytes sent.
2286 """
2287 server, client = self._loopback()
2288 count = server.send(buffer(b('xy')))
2289 self.assertEquals(count, 2)
2290 self.assertEquals(client.recv(2), b('xy'))
2291
2292
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002293
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002294class ConnectionSendallTests(TestCase, _LoopbackMixin):
2295 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002296 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002297 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002298 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002299 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002300 When called with arguments other than a string argument for its first
2301 parameter or with more than two arguments, :py:obj:`Connection.sendall`
2302 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002303 """
2304 connection = Connection(Context(TLSv1_METHOD), None)
2305 self.assertRaises(TypeError, connection.sendall)
2306 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002307 self.assertRaises(
2308 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002309
2310
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002311 def test_short(self):
2312 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002313 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002314 it.
2315 """
2316 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04002317 server.sendall(b('x'))
2318 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002319
2320
Abraham Martinef063482015-03-25 14:06:24 +00002321 def test_text(self):
2322 """
2323 :py:obj:`Connection.sendall` transmits all the content in the string passed to
2324 it raising a DepreactionWarning in case of this being a text.
2325 """
2326 server, client = self._loopback()
2327 with catch_warnings(record=True) as w:
2328 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002329 server.sendall("x".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002330 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002331 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002332 WARNING_TYPE_EXPECTED
2333 ),
2334 str(w[-1].message)
2335 )
2336 self.assertIs(w[-1].category, DeprecationWarning)
2337 self.assertEquals(client.recv(1), b"x")
Abraham Martinef063482015-03-25 14:06:24 +00002338
2339
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002340 try:
2341 memoryview
2342 except NameError:
2343 "cannot test sending memoryview without memoryview"
2344 else:
2345 def test_short_memoryview(self):
2346 """
2347 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002348 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002349 """
2350 server, client = self._loopback()
2351 server.sendall(memoryview(b('x')))
2352 self.assertEquals(client.recv(1), b('x'))
2353
2354
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002355 try:
2356 buffer
2357 except NameError:
2358 "cannot test sending buffers without buffers"
2359 else:
2360 def test_short_buffers(self):
2361 """
2362 When passed a buffer containing a small number of bytes,
2363 :py:obj:`Connection.sendall` transmits all of them.
2364 """
2365 server, client = self._loopback()
2366 server.sendall(buffer(b('x')))
2367 self.assertEquals(client.recv(1), b('x'))
2368
2369
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002370 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002371 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002372 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002373 it even if this requires multiple calls of an underlying write function.
2374 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002375 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04002376 # Should be enough, underlying SSL_write should only do 16k at a time.
2377 # On Windows, after 32k of bytes the write will block (forever - because
2378 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04002379 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002380 server.sendall(message)
2381 accum = []
2382 received = 0
2383 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04002384 data = client.recv(1024)
2385 accum.append(data)
2386 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04002387 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002388
2389
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002390 def test_closed(self):
2391 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002392 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002393 write error from the low level write call.
2394 """
2395 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04002396 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002397 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02002398 if platform == "win32":
2399 self.assertEqual(exc.args[0], ESHUTDOWN)
2400 else:
2401 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002402
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002403
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002404
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002405class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
2406 """
2407 Tests for SSL renegotiation APIs.
2408 """
2409 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002410 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002411 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002412 arguments.
2413 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002414 connection = Connection(Context(TLSv1_METHOD), None)
2415 self.assertRaises(TypeError, connection.renegotiate, None)
2416
2417
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002418 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002419 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002420 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002421 any arguments.
2422 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002423 connection = Connection(Context(TLSv1_METHOD), None)
2424 self.assertRaises(TypeError, connection.total_renegotiations, None)
2425
2426
2427 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002428 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002429 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002430 renegotiations have happened.
2431 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002432 connection = Connection(Context(TLSv1_METHOD), None)
2433 self.assertEquals(connection.total_renegotiations(), 0)
2434
2435
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002436# def test_renegotiate(self):
2437# """
2438# """
2439# server, client = self._loopback()
2440
2441# server.send("hello world")
2442# self.assertEquals(client.recv(len("hello world")), "hello world")
2443
2444# self.assertEquals(server.total_renegotiations(), 0)
2445# self.assertTrue(server.renegotiate())
2446
2447# server.setblocking(False)
2448# client.setblocking(False)
2449# while server.renegotiate_pending():
2450# client.do_handshake()
2451# server.do_handshake()
2452
2453# self.assertEquals(server.total_renegotiations(), 1)
2454
2455
2456
2457
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002458class ErrorTests(TestCase):
2459 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002460 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002461 """
2462 def test_type(self):
2463 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002464 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002465 """
2466 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05002467 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05002468
2469
2470
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002471class ConstantsTests(TestCase):
2472 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002473 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002474
2475 These are values defined by OpenSSL intended only to be used as flags to
2476 OpenSSL APIs. The only assertions it seems can be made about them is
2477 their values.
2478 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002479 # unittest.TestCase has no skip mechanism
2480 if OP_NO_QUERY_MTU is not None:
2481 def test_op_no_query_mtu(self):
2482 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002483 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002484 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002485 """
2486 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
2487 else:
2488 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002489
2490
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002491 if OP_COOKIE_EXCHANGE is not None:
2492 def test_op_cookie_exchange(self):
2493 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002494 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002495 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002496 """
2497 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
2498 else:
2499 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002500
2501
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002502 if OP_NO_TICKET is not None:
2503 def test_op_no_ticket(self):
2504 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002505 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002506 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002507 """
2508 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04002509 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002510 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05002511
2512
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002513 if OP_NO_COMPRESSION is not None:
2514 def test_op_no_compression(self):
2515 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002516 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
2517 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002518 """
2519 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
2520 else:
2521 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
2522
2523
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002524 def test_sess_cache_off(self):
2525 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002526 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
2527 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002528 """
2529 self.assertEqual(0x0, SESS_CACHE_OFF)
2530
2531
2532 def test_sess_cache_client(self):
2533 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002534 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
2535 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002536 """
2537 self.assertEqual(0x1, SESS_CACHE_CLIENT)
2538
2539
2540 def test_sess_cache_server(self):
2541 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002542 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
2543 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002544 """
2545 self.assertEqual(0x2, SESS_CACHE_SERVER)
2546
2547
2548 def test_sess_cache_both(self):
2549 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002550 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
2551 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002552 """
2553 self.assertEqual(0x3, SESS_CACHE_BOTH)
2554
2555
2556 def test_sess_cache_no_auto_clear(self):
2557 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002558 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
2559 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
2560 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002561 """
2562 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
2563
2564
2565 def test_sess_cache_no_internal_lookup(self):
2566 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002567 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
2568 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
2569 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002570 """
2571 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
2572
2573
2574 def test_sess_cache_no_internal_store(self):
2575 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002576 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
2577 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
2578 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002579 """
2580 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
2581
2582
2583 def test_sess_cache_no_internal(self):
2584 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002585 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
2586 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
2587 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002588 """
2589 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
2590
2591
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04002592
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002593class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05002594 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002595 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05002596 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002597 def _server(self, sock):
2598 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002599 Create a new server-side SSL :py:obj:`Connection` object wrapped around
2600 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002601 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002602 # Create the server side Connection. This is mostly setup boilerplate
2603 # - use TLSv1, use a particular certificate, etc.
2604 server_ctx = Context(TLSv1_METHOD)
2605 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2606 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2607 server_store = server_ctx.get_cert_store()
2608 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2609 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2610 server_ctx.check_privatekey()
2611 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002612 # Here the Connection is actually created. If None is passed as the 2nd
2613 # parameter, it indicates a memory BIO should be created.
2614 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002615 server_conn.set_accept_state()
2616 return server_conn
2617
2618
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002619 def _client(self, sock):
2620 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002621 Create a new client-side SSL :py:obj:`Connection` object wrapped around
2622 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002623 """
2624 # Now create the client side Connection. Similar boilerplate to the
2625 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002626 client_ctx = Context(TLSv1_METHOD)
2627 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2628 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2629 client_store = client_ctx.get_cert_store()
2630 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
2631 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
2632 client_ctx.check_privatekey()
2633 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002634 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002635 client_conn.set_connect_state()
2636 return client_conn
2637
2638
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002639 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002640 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002641 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002642 reading from the output of each and writing those bytes to the input of
2643 the other and in this way establish a connection and exchange
2644 application-level bytes with each other.
2645 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002646 server_conn = self._server(None)
2647 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002648
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002649 # There should be no key or nonces yet.
2650 self.assertIdentical(server_conn.master_key(), None)
2651 self.assertIdentical(server_conn.client_random(), None)
2652 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002653
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002654 # First, the handshake needs to happen. We'll deliver bytes back and
2655 # forth between the client and server until neither of them feels like
2656 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002657 self.assertIdentical(
2658 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002659
2660 # Now that the handshake is done, there should be a key and nonces.
2661 self.assertNotIdentical(server_conn.master_key(), None)
2662 self.assertNotIdentical(server_conn.client_random(), None)
2663 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04002664 self.assertEquals(server_conn.client_random(), client_conn.client_random())
2665 self.assertEquals(server_conn.server_random(), client_conn.server_random())
2666 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
2667 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002668
2669 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002670 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05002671
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002672 server_conn.write(important_message)
2673 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002674 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002675 (client_conn, important_message))
2676
2677 client_conn.write(important_message[::-1])
2678 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002679 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002680 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05002681
2682
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002683 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05002684 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002685 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002686
2687 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09002688 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002689 this test fails, there must be a problem outside the memory BIO
2690 code, as no memory BIO is involved here). Even though this isn't a
2691 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05002692 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04002693 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05002694
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002695 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05002696 client_conn.send(important_message)
2697 msg = server_conn.recv(1024)
2698 self.assertEqual(msg, important_message)
2699
2700 # Again in the other direction, just for fun.
2701 important_message = important_message[::-1]
2702 server_conn.send(important_message)
2703 msg = client_conn.recv(1024)
2704 self.assertEqual(msg, important_message)
2705
2706
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04002707 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05002708 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002709 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
2710 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05002711 """
2712 context = Context(SSLv3_METHOD)
2713 client = socket()
2714 clientSSL = Connection(context, client)
2715 self.assertRaises( TypeError, clientSSL.bio_read, 100)
2716 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04002717 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002718
2719
2720 def test_outgoingOverflow(self):
2721 """
2722 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002723 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002724 returned and that many bytes from the beginning of the input can be
2725 read from the other end of the connection.
2726 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002727 server = self._server(None)
2728 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002729
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002730 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002731
2732 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002733 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002734 # Sanity check. We're trying to test what happens when the entire
2735 # input can't be sent. If the entire input was sent, this test is
2736 # meaningless.
2737 self.assertTrue(sent < size)
2738
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002739 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002740 self.assertIdentical(receiver, server)
2741
2742 # We can rely on all of these bytes being received at once because
2743 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
2744 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002745
2746
2747 def test_shutdown(self):
2748 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002749 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
2750 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002751 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002752 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002753 server.bio_shutdown()
2754 e = self.assertRaises(Error, server.recv, 1024)
2755 # We don't want WantReadError or ZeroReturnError or anything - it's a
2756 # handshake failure.
2757 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002758
2759
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002760 def test_unexpectedEndOfFile(self):
2761 """
2762 If the connection is lost before an orderly SSL shutdown occurs,
2763 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
2764 "Unexpected EOF".
2765 """
2766 server_conn, client_conn = self._loopback()
2767 client_conn.sock_shutdown(SHUT_RDWR)
2768 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
2769 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
2770
2771
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002772 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002773 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002774 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 -04002775
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002776 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002777 before the client and server are connected to each other. This
2778 function should specify a list of CAs for the server to send to the
2779 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09002780 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002781 times.
2782 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002783 server = self._server(None)
2784 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002785 self.assertEqual(client.get_client_ca_list(), [])
2786 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002787 ctx = server.get_context()
2788 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002789 self.assertEqual(client.get_client_ca_list(), [])
2790 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002791 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002792 self.assertEqual(client.get_client_ca_list(), expected)
2793 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002794
2795
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002796 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002797 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002798 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002799 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002800 """
2801 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002802 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
2803 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
2804 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002805
2806
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002807 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002808 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002809 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002810 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09002811 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002812 after the connection is set up.
2813 """
2814 def no_ca(ctx):
2815 ctx.set_client_ca_list([])
2816 return []
2817 self._check_client_ca_list(no_ca)
2818
2819
2820 def test_set_one_ca_list(self):
2821 """
2822 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002823 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002824 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002825 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002826 X509Name after the connection is set up.
2827 """
2828 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2829 cadesc = cacert.get_subject()
2830 def single_ca(ctx):
2831 ctx.set_client_ca_list([cadesc])
2832 return [cadesc]
2833 self._check_client_ca_list(single_ca)
2834
2835
2836 def test_set_multiple_ca_list(self):
2837 """
2838 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002839 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002840 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002841 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002842 X509Names after the connection is set up.
2843 """
2844 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2845 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2846
2847 sedesc = secert.get_subject()
2848 cldesc = clcert.get_subject()
2849
2850 def multiple_ca(ctx):
2851 L = [sedesc, cldesc]
2852 ctx.set_client_ca_list(L)
2853 return L
2854 self._check_client_ca_list(multiple_ca)
2855
2856
2857 def test_reset_ca_list(self):
2858 """
2859 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09002860 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002861 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002862 """
2863 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2864 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2865 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2866
2867 cadesc = cacert.get_subject()
2868 sedesc = secert.get_subject()
2869 cldesc = clcert.get_subject()
2870
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002871 def changed_ca(ctx):
2872 ctx.set_client_ca_list([sedesc, cldesc])
2873 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002874 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002875 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002876
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002877
2878 def test_mutated_ca_list(self):
2879 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002880 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002881 afterwards, this does not affect the list of CA names sent to the
2882 client.
2883 """
2884 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2885 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2886
2887 cadesc = cacert.get_subject()
2888 sedesc = secert.get_subject()
2889
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002890 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002891 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002892 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002893 L.append(sedesc)
2894 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002895 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002896
2897
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002898 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002899 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002900 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002901 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002902 """
2903 ctx = Context(TLSv1_METHOD)
2904 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002905 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002906 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002907 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002908
2909
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002910 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002911 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002912 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09002913 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002914 """
2915 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2916 cadesc = cacert.get_subject()
2917 def single_ca(ctx):
2918 ctx.add_client_ca(cacert)
2919 return [cadesc]
2920 self._check_client_ca_list(single_ca)
2921
2922
2923 def test_multiple_add_client_ca(self):
2924 """
2925 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09002926 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002927 """
2928 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2929 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2930
2931 cadesc = cacert.get_subject()
2932 sedesc = secert.get_subject()
2933
2934 def multiple_ca(ctx):
2935 ctx.add_client_ca(cacert)
2936 ctx.add_client_ca(secert)
2937 return [cadesc, sedesc]
2938 self._check_client_ca_list(multiple_ca)
2939
2940
2941 def test_set_and_add_client_ca(self):
2942 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002943 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
2944 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002945 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002946 """
2947 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2948 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2949 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2950
2951 cadesc = cacert.get_subject()
2952 sedesc = secert.get_subject()
2953 cldesc = clcert.get_subject()
2954
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002955 def mixed_set_add_ca(ctx):
2956 ctx.set_client_ca_list([cadesc, sedesc])
2957 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002958 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002959 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002960
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002961
2962 def test_set_after_add_client_ca(self):
2963 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002964 A call to :py:obj:`Context.set_client_ca_list` after a call to
2965 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002966 call with the names specified by the latter cal.
2967 """
2968 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2969 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2970 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2971
2972 cadesc = cacert.get_subject()
2973 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002974
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002975 def set_replaces_add_ca(ctx):
2976 ctx.add_client_ca(clcert)
2977 ctx.set_client_ca_list([cadesc])
2978 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002979 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002980 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002981
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002982
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002983
2984class ConnectionBIOTests(TestCase):
2985 """
2986 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
2987 """
2988 def test_wantReadError(self):
2989 """
2990 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
2991 if there are no bytes available to be read from the BIO.
2992 """
2993 ctx = Context(TLSv1_METHOD)
2994 conn = Connection(ctx, None)
2995 self.assertRaises(WantReadError, conn.bio_read, 1024)
2996
2997
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002998 def test_buffer_size(self):
2999 """
3000 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3001 number of bytes to read and return.
3002 """
3003 ctx = Context(TLSv1_METHOD)
3004 conn = Connection(ctx, None)
3005 conn.set_connect_state()
3006 try:
3007 conn.do_handshake()
3008 except WantReadError:
3009 pass
3010 data = conn.bio_read(2)
3011 self.assertEqual(2, len(data))
3012
3013
3014 if not PY3:
3015 def test_buffer_size_long(self):
3016 """
3017 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3018 :py:obj:`long` as well as :py:obj:`int`.
3019 """
3020 ctx = Context(TLSv1_METHOD)
3021 conn = Connection(ctx, None)
3022 conn.set_connect_state()
3023 try:
3024 conn.do_handshake()
3025 except WantReadError:
3026 pass
3027 data = conn.bio_read(long(2))
3028 self.assertEqual(2, len(data))
3029
3030
3031
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003032
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003033class InfoConstantTests(TestCase):
3034 """
3035 Tests for assorted constants exposed for use in info callbacks.
3036 """
3037 def test_integers(self):
3038 """
3039 All of the info constants are integers.
3040
3041 This is a very weak test. It would be nice to have one that actually
3042 verifies that as certain info events happen, the value passed to the
3043 info callback matches up with the constant exposed by OpenSSL.SSL.
3044 """
3045 for const in [
3046 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3047 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3048 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3049 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3050 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
3051 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
3052
3053 self.assertTrue(isinstance(const, int))
3054
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003055
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003056if __name__ == '__main__':
3057 main()