blob: ca896d98a6b35c29f9b054974cb9a4728dc6121c [file] [log] [blame]
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05001# Copyright (C) Jean-Paul Calderone
2# See LICENSE for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04003
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04004"""
Jonathan Ballet648875f2011-07-16 14:14:58 +09005Unit tests for :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04006"""
7
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05008from gc import collect, get_referrers
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02009from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE, ESHUTDOWN
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040010from sys import platform, version_info
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070011from socket import SHUT_RDWR, error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040012from os import makedirs
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040013from os.path import join
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -040014from unittest import main
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040015from weakref import ref
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050016
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -040017from six import PY3, text_type, u
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050018
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040019from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080020from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040021from OpenSSL.crypto import dump_privatekey, load_privatekey
22from OpenSSL.crypto import dump_certificate, load_certificate
23
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040024from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
25from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040026from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040027from OpenSSL.SSL import (
28 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
29 TLSv1_1_METHOD, TLSv1_2_METHOD)
30from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040031from OpenSSL.SSL import (
32 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040033
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040034from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050035 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
36 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
37 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
Andy Lutomirskif05a2732014-03-13 17:22:25 -070038from OpenSSL.SSL import (
Andy Lutomirski61d7d392014-04-04 12:16:56 -070039 _Cryptography_HAS_EC, ELLIPTIC_CURVE_DESCRIPTIONS,
40 ECNotAvailable, UnknownObject)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050041
42from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070043 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050044from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070045 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040046
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050047from OpenSSL.test.util import TestCase, b
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040048from OpenSSL.test.test_crypto import (
49 cleartextCertificatePEM, cleartextPrivateKeyPEM)
50from OpenSSL.test.test_crypto import (
51 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
52 root_cert_pem)
53
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050054try:
55 from OpenSSL.SSL import OP_NO_QUERY_MTU
56except ImportError:
57 OP_NO_QUERY_MTU = None
58try:
59 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
60except ImportError:
61 OP_COOKIE_EXCHANGE = None
62try:
63 from OpenSSL.SSL import OP_NO_TICKET
64except ImportError:
65 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040066
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040067try:
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -040068 from OpenSSL.SSL import OP_NO_COMPRESSION
69except ImportError:
70 OP_NO_COMPRESSION = None
71
72try:
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040073 from OpenSSL.SSL import MODE_RELEASE_BUFFERS
74except ImportError:
75 MODE_RELEASE_BUFFERS = None
76
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040077try:
78 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
79except ImportError:
80 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
81
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040082from OpenSSL.SSL import (
83 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
84 SSL_ST_OK, SSL_ST_RENEGOTIATE,
85 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
86 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
87 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
88 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040089
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040090# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
91# to use)
92dhparam = """\
93-----BEGIN DH PARAMETERS-----
94MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
95-----END DH PARAMETERS-----
96"""
97
98
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040099def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400100 return ok
101
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400102
Rick Deanb1ccd562009-07-09 23:52:39 -0500103def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400104 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400105 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400106 """
107 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500108 port = socket()
109 port.bind(('', 0))
110 port.listen(1)
111 client = socket()
112 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400113 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400114 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500115 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500116
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400117 # Let's pass some unencrypted data to make sure our socket connection is
118 # fine. Just one byte, so we don't have to worry about buffers getting
119 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400120 server.send(b("x"))
121 assert client.recv(1024) == b("x")
122 client.send(b("y"))
123 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500124
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400125 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400126 server.setblocking(False)
127 client.setblocking(False)
128
Rick Deanb1ccd562009-07-09 23:52:39 -0500129 return (server, client)
130
131
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400132
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400133def handshake(client, server):
134 conns = [client, server]
135 while conns:
136 for conn in conns:
137 try:
138 conn.do_handshake()
139 except WantReadError:
140 pass
141 else:
142 conns.remove(conn)
143
144
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400145def _create_certificate_chain():
146 """
147 Construct and return a chain of certificates.
148
149 1. A new self-signed certificate authority certificate (cacert)
150 2. A new intermediate certificate signed by cacert (icert)
151 3. A new server certificate signed by icert (scert)
152 """
153 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
154
155 # Step 1
156 cakey = PKey()
157 cakey.generate_key(TYPE_RSA, 512)
158 cacert = X509()
159 cacert.get_subject().commonName = "Authority Certificate"
160 cacert.set_issuer(cacert.get_subject())
161 cacert.set_pubkey(cakey)
162 cacert.set_notBefore(b("20000101000000Z"))
163 cacert.set_notAfter(b("20200101000000Z"))
164 cacert.add_extensions([caext])
165 cacert.set_serial_number(0)
166 cacert.sign(cakey, "sha1")
167
168 # Step 2
169 ikey = PKey()
170 ikey.generate_key(TYPE_RSA, 512)
171 icert = X509()
172 icert.get_subject().commonName = "Intermediate Certificate"
173 icert.set_issuer(cacert.get_subject())
174 icert.set_pubkey(ikey)
175 icert.set_notBefore(b("20000101000000Z"))
176 icert.set_notAfter(b("20200101000000Z"))
177 icert.add_extensions([caext])
178 icert.set_serial_number(0)
179 icert.sign(cakey, "sha1")
180
181 # Step 3
182 skey = PKey()
183 skey.generate_key(TYPE_RSA, 512)
184 scert = X509()
185 scert.get_subject().commonName = "Server Certificate"
186 scert.set_issuer(icert.get_subject())
187 scert.set_pubkey(skey)
188 scert.set_notBefore(b("20000101000000Z"))
189 scert.set_notAfter(b("20200101000000Z"))
190 scert.add_extensions([
191 X509Extension(b('basicConstraints'), True, b('CA:false'))])
192 scert.set_serial_number(0)
193 scert.sign(ikey, "sha1")
194
195 return [(cakey, cacert), (ikey, icert), (skey, scert)]
196
197
198
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400199class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400200 """
201 Helper mixin which defines methods for creating a connected socket pair and
202 for forcing two connected SSL sockets to talk to each other via memory BIOs.
203 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500204 def _loopbackClientFactory(self, socket):
205 client = Connection(Context(TLSv1_METHOD), socket)
206 client.set_connect_state()
207 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400208
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500209
210 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400211 ctx = Context(TLSv1_METHOD)
212 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
213 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500214 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400215 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500216 return server
217
218
219 def _loopback(self, serverFactory=None, clientFactory=None):
220 if serverFactory is None:
221 serverFactory = self._loopbackServerFactory
222 if clientFactory is None:
223 clientFactory = self._loopbackClientFactory
224
225 (server, client) = socket_pair()
226 server = serverFactory(server)
227 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400228
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400229 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400230
231 server.setblocking(True)
232 client.setblocking(True)
233 return server, client
234
235
236 def _interactInMemory(self, client_conn, server_conn):
237 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900238 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400239 objects. Copy bytes back and forth between their send/receive buffers
240 for as long as there is anything to copy. When there is nothing more
Jonathan Ballet648875f2011-07-16 14:14:58 +0900241 to copy, return :py:obj:`None`. If one of them actually manages to deliver
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400242 some application bytes, return a two-tuple of the connection from which
243 the bytes were read and the bytes themselves.
244 """
245 wrote = True
246 while wrote:
247 # Loop until neither side has anything to say
248 wrote = False
249
250 # Copy stuff from each side's send buffer to the other side's
251 # receive buffer.
252 for (read, write) in [(client_conn, server_conn),
253 (server_conn, client_conn)]:
254
255 # Give the side a chance to generate some more bytes, or
256 # succeed.
257 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400258 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400259 except WantReadError:
260 # It didn't succeed, so we'll hope it generated some
261 # output.
262 pass
263 else:
264 # It did succeed, so we'll stop now and let the caller deal
265 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400266 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400267
268 while True:
269 # Keep copying as long as there's more stuff there.
270 try:
271 dirty = read.bio_read(4096)
272 except WantReadError:
273 # Okay, nothing more waiting to be sent. Stop
274 # processing this send buffer.
275 break
276 else:
277 # Keep track of the fact that someone generated some
278 # output.
279 wrote = True
280 write.bio_write(dirty)
281
282
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400283
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400284class VersionTests(TestCase):
285 """
286 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900287 :py:obj:`OpenSSL.SSL.SSLeay_version` and
288 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400289 """
290 def test_OPENSSL_VERSION_NUMBER(self):
291 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900292 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400293 byte and the patch, fix, minor, and major versions in the
294 nibbles above that.
295 """
296 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
297
298
299 def test_SSLeay_version(self):
300 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900301 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400302 one of a number of version strings based on that indicator.
303 """
304 versions = {}
305 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
306 SSLEAY_PLATFORM, SSLEAY_DIR]:
307 version = SSLeay_version(t)
308 versions[version] = t
309 self.assertTrue(isinstance(version, bytes))
310 self.assertEqual(len(versions), 5)
311
312
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400313
314class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400315 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900316 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400317 """
318 def test_method(self):
319 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900320 :py:obj:`Context` can be instantiated with one of :py:obj:`SSLv2_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400321 :py:obj:`SSLv3_METHOD`, :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
322 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400323 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400324 methods = [
325 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
326 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400327 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400328
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400329
330 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
331 for meth in maybe:
332 try:
333 Context(meth)
334 except (Error, ValueError):
335 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
336 # don't. Difficult to say in advance.
337 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400338
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400339 self.assertRaises(TypeError, Context, "")
340 self.assertRaises(ValueError, Context, 10)
341
342
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500343 if not PY3:
344 def test_method_long(self):
345 """
346 On Python 2 :py:class:`Context` accepts values of type
347 :py:obj:`long` as well as :py:obj:`int`.
348 """
349 Context(long(TLSv1_METHOD))
350
351
352
Rick Deane15b1472009-07-09 15:53:42 -0500353 def test_type(self):
354 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900355 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400356 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500357 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400358 self.assertIdentical(Context, ContextType)
359 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500360
361
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400362 def test_use_privatekey(self):
363 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900364 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400365 """
366 key = PKey()
367 key.generate_key(TYPE_RSA, 128)
368 ctx = Context(TLSv1_METHOD)
369 ctx.use_privatekey(key)
370 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400371
372
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800373 def test_use_privatekey_file_missing(self):
374 """
375 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error`
376 when passed the name of a file which does not exist.
377 """
378 ctx = Context(TLSv1_METHOD)
379 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
380
381
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500382 if not PY3:
383 def test_use_privatekey_file_long(self):
384 """
385 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
386 filetype of type :py:obj:`long` as well as :py:obj:`int`.
387 """
388 pemfile = self.mktemp()
389
390 key = PKey()
391 key.generate_key(TYPE_RSA, 128)
392
393 with open(pemfile, "wt") as pem:
394 pem.write(
395 dump_privatekey(FILETYPE_PEM, key).decode("ascii"))
396
397 ctx = Context(TLSv1_METHOD)
398 ctx.use_privatekey_file(pemfile, long(FILETYPE_PEM))
399
400
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800401 def test_use_certificate_wrong_args(self):
402 """
403 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
404 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as an
405 argument.
406 """
407 ctx = Context(TLSv1_METHOD)
408 self.assertRaises(TypeError, ctx.use_certificate)
409 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
410 self.assertRaises(TypeError, ctx.use_certificate, X509(), "hello, world")
411
412
413 def test_use_certificate_uninitialized(self):
414 """
415 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
416 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
417 initialized (ie, which does not actually have any certificate data).
418 """
419 ctx = Context(TLSv1_METHOD)
420 self.assertRaises(Error, ctx.use_certificate, X509())
421
422
423 def test_use_certificate(self):
424 """
425 :py:obj:`Context.use_certificate` sets the certificate which will be
426 used to identify connections created using the context.
427 """
428 # TODO
429 # Hard to assert anything. But we could set a privatekey then ask
430 # OpenSSL if the cert and key agree using check_privatekey. Then as
431 # long as check_privatekey works right we're good...
432 ctx = Context(TLSv1_METHOD)
433 ctx.use_certificate(load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
434
435
436 def test_use_certificate_file_wrong_args(self):
437 """
438 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
439 called with zero arguments or more than two arguments, or if the first
440 argument is not a byte string or the second argumnent is not an integer.
441 """
442 ctx = Context(TLSv1_METHOD)
443 self.assertRaises(TypeError, ctx.use_certificate_file)
444 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile", object())
445 self.assertRaises(
446 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM, object())
447 self.assertRaises(
448 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
449 self.assertRaises(
450 TypeError, ctx.use_certificate_file, b"somefile", object())
451
452
453 def test_use_certificate_file_missing(self):
454 """
455 :py:obj:`Context.use_certificate_file` raises
456 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does not
457 exist.
458 """
459 ctx = Context(TLSv1_METHOD)
460 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
461
462
463 def test_use_certificate_file(self):
464 """
465 :py:obj:`Context.use_certificate` sets the certificate which will be
466 used to identify connections created using the context.
467 """
468 # TODO
469 # Hard to assert anything. But we could set a privatekey then ask
470 # OpenSSL if the cert and key agree using check_privatekey. Then as
471 # long as check_privatekey works right we're good...
472 pem_filename = self.mktemp()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500473 with open(pem_filename, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800474 pem_file.write(cleartextCertificatePEM)
475
476 ctx = Context(TLSv1_METHOD)
477 ctx.use_certificate_file(pem_filename)
478
479
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500480 if not PY3:
481 def test_use_certificate_file_long(self):
482 """
483 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
484 filetype of type :py:obj:`long` as well as :py:obj:`int`.
485 """
486 pem_filename = self.mktemp()
487 with open(pem_filename, "wb") as pem_file:
488 pem_file.write(cleartextCertificatePEM)
489
490 ctx = Context(TLSv1_METHOD)
491 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
492
493
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400494 def test_set_app_data_wrong_args(self):
495 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900496 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called with other than
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400497 one argument.
498 """
499 context = Context(TLSv1_METHOD)
500 self.assertRaises(TypeError, context.set_app_data)
501 self.assertRaises(TypeError, context.set_app_data, None, None)
502
503
504 def test_get_app_data_wrong_args(self):
505 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900506 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400507 arguments.
508 """
509 context = Context(TLSv1_METHOD)
510 self.assertRaises(TypeError, context.get_app_data, None)
511
512
513 def test_app_data(self):
514 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900515 :py:obj:`Context.set_app_data` stores an object for later retrieval using
516 :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400517 """
518 app_data = object()
519 context = Context(TLSv1_METHOD)
520 context.set_app_data(app_data)
521 self.assertIdentical(context.get_app_data(), app_data)
522
523
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400524 def test_set_options_wrong_args(self):
525 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900526 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with the wrong
527 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400528 """
529 context = Context(TLSv1_METHOD)
530 self.assertRaises(TypeError, context.set_options)
531 self.assertRaises(TypeError, context.set_options, None)
532 self.assertRaises(TypeError, context.set_options, 1, None)
533
534
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500535 def test_set_options(self):
536 """
537 :py:obj:`Context.set_options` returns the new options value.
538 """
539 context = Context(TLSv1_METHOD)
540 options = context.set_options(OP_NO_SSLv2)
541 self.assertTrue(OP_NO_SSLv2 & options)
542
543
544 if not PY3:
545 def test_set_options_long(self):
546 """
547 On Python 2 :py:obj:`Context.set_options` accepts values of type
548 :py:obj:`long` as well as :py:obj:`int`.
549 """
550 context = Context(TLSv1_METHOD)
551 options = context.set_options(long(OP_NO_SSLv2))
552 self.assertTrue(OP_NO_SSLv2 & options)
553
554
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300555 def test_set_mode_wrong_args(self):
556 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400557 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with the wrong
558 number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300559 """
560 context = Context(TLSv1_METHOD)
561 self.assertRaises(TypeError, context.set_mode)
562 self.assertRaises(TypeError, context.set_mode, None)
563 self.assertRaises(TypeError, context.set_mode, 1, None)
564
565
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400566 if MODE_RELEASE_BUFFERS is not None:
567 def test_set_mode(self):
568 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400569 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the newly
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400570 set mode.
571 """
572 context = Context(TLSv1_METHOD)
573 self.assertTrue(
574 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500575
576 if not PY3:
577 def test_set_mode_long(self):
578 """
579 On Python 2 :py:obj:`Context.set_mode` accepts values of type
580 :py:obj:`long` as well as :py:obj:`int`.
581 """
582 context = Context(TLSv1_METHOD)
583 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
584 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400585 else:
586 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
587
588
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400589 def test_set_timeout_wrong_args(self):
590 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900591 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with the wrong
592 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400593 """
594 context = Context(TLSv1_METHOD)
595 self.assertRaises(TypeError, context.set_timeout)
596 self.assertRaises(TypeError, context.set_timeout, None)
597 self.assertRaises(TypeError, context.set_timeout, 1, None)
598
599
600 def test_get_timeout_wrong_args(self):
601 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900602 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400603 """
604 context = Context(TLSv1_METHOD)
605 self.assertRaises(TypeError, context.get_timeout, None)
606
607
608 def test_timeout(self):
609 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900610 :py:obj:`Context.set_timeout` sets the session timeout for all connections
611 created using the context object. :py:obj:`Context.get_timeout` retrieves this
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400612 value.
613 """
614 context = Context(TLSv1_METHOD)
615 context.set_timeout(1234)
616 self.assertEquals(context.get_timeout(), 1234)
617
618
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500619 if not PY3:
620 def test_timeout_long(self):
621 """
622 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
623 `long` as well as int.
624 """
625 context = Context(TLSv1_METHOD)
626 context.set_timeout(long(1234))
627 self.assertEquals(context.get_timeout(), 1234)
628
629
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400630 def test_set_verify_depth_wrong_args(self):
631 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900632 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called with the wrong
633 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400634 """
635 context = Context(TLSv1_METHOD)
636 self.assertRaises(TypeError, context.set_verify_depth)
637 self.assertRaises(TypeError, context.set_verify_depth, None)
638 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
639
640
641 def test_get_verify_depth_wrong_args(self):
642 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900643 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400644 """
645 context = Context(TLSv1_METHOD)
646 self.assertRaises(TypeError, context.get_verify_depth, None)
647
648
649 def test_verify_depth(self):
650 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900651 :py:obj:`Context.set_verify_depth` sets the number of certificates in a chain
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400652 to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900653 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400654 """
655 context = Context(TLSv1_METHOD)
656 context.set_verify_depth(11)
657 self.assertEquals(context.get_verify_depth(), 11)
658
659
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500660 if not PY3:
661 def test_verify_depth_long(self):
662 """
663 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
664 type `long` as well as int.
665 """
666 context = Context(TLSv1_METHOD)
667 context.set_verify_depth(long(11))
668 self.assertEquals(context.get_verify_depth(), 11)
669
670
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400671 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400672 """
673 Write a new private key out to a new file, encrypted using the given
674 passphrase. Return the path to the new file.
675 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400676 key = PKey()
677 key.generate_key(TYPE_RSA, 128)
678 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400679 fObj = open(pemFile, 'w')
680 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
681 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400682 fObj.close()
683 return pemFile
684
685
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400686 def test_set_passwd_cb_wrong_args(self):
687 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900688 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called with the
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400689 wrong arguments or with a non-callable first argument.
690 """
691 context = Context(TLSv1_METHOD)
692 self.assertRaises(TypeError, context.set_passwd_cb)
693 self.assertRaises(TypeError, context.set_passwd_cb, None)
694 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
695
696
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400697 def test_set_passwd_cb(self):
698 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900699 :py:obj:`Context.set_passwd_cb` accepts a callable which will be invoked when
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400700 a private key is loaded from an encrypted PEM.
701 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400702 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400703 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400704 calledWith = []
705 def passphraseCallback(maxlen, verify, extra):
706 calledWith.append((maxlen, verify, extra))
707 return passphrase
708 context = Context(TLSv1_METHOD)
709 context.set_passwd_cb(passphraseCallback)
710 context.use_privatekey_file(pemFile)
711 self.assertTrue(len(calledWith), 1)
712 self.assertTrue(isinstance(calledWith[0][0], int))
713 self.assertTrue(isinstance(calledWith[0][1], int))
714 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400715
716
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400717 def test_passwd_callback_exception(self):
718 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900719 :py:obj:`Context.use_privatekey_file` propagates any exception raised by the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400720 passphrase callback.
721 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400722 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400723 def passphraseCallback(maxlen, verify, extra):
724 raise RuntimeError("Sorry, I am a fail.")
725
726 context = Context(TLSv1_METHOD)
727 context.set_passwd_cb(passphraseCallback)
728 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
729
730
731 def test_passwd_callback_false(self):
732 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900733 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400734 passphrase callback returns a false value.
735 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400736 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400737 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500738 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400739
740 context = Context(TLSv1_METHOD)
741 context.set_passwd_cb(passphraseCallback)
742 self.assertRaises(Error, context.use_privatekey_file, pemFile)
743
744
745 def test_passwd_callback_non_string(self):
746 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900747 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400748 passphrase callback returns a true non-string value.
749 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400750 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400751 def passphraseCallback(maxlen, verify, extra):
752 return 10
753
754 context = Context(TLSv1_METHOD)
755 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800756 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400757
758
759 def test_passwd_callback_too_long(self):
760 """
761 If the passphrase returned by the passphrase callback returns a string
762 longer than the indicated maximum length, it is truncated.
763 """
764 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400765 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400766 pemFile = self._write_encrypted_pem(passphrase)
767 def passphraseCallback(maxlen, verify, extra):
768 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400769 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400770
771 context = Context(TLSv1_METHOD)
772 context.set_passwd_cb(passphraseCallback)
773 # This shall succeed because the truncated result is the correct
774 # passphrase.
775 context.use_privatekey_file(pemFile)
776
777
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400778 def test_set_info_callback(self):
779 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900780 :py:obj:`Context.set_info_callback` accepts a callable which will be invoked
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400781 when certain information about an SSL connection is available.
782 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500783 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400784
785 clientSSL = Connection(Context(TLSv1_METHOD), client)
786 clientSSL.set_connect_state()
787
788 called = []
789 def info(conn, where, ret):
790 called.append((conn, where, ret))
791 context = Context(TLSv1_METHOD)
792 context.set_info_callback(info)
793 context.use_certificate(
794 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
795 context.use_privatekey(
796 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
797
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400798 serverSSL = Connection(context, server)
799 serverSSL.set_accept_state()
800
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500801 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400802
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500803 # The callback must always be called with a Connection instance as the
804 # first argument. It would probably be better to split this into
805 # separate tests for client and server side info callbacks so we could
806 # assert it is called with the right Connection instance. It would
807 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500808 notConnections = [
809 conn for (conn, where, ret) in called
810 if not isinstance(conn, Connection)]
811 self.assertEqual(
812 [], notConnections,
813 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400814
815
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400816 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400817 """
818 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400819 its :py:obj:`load_verify_locations` method with the given arguments.
820 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400821 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500822 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400823
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400824 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400825 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400826 # Require that the server certificate verify properly or the
827 # connection will fail.
828 clientContext.set_verify(
829 VERIFY_PEER,
830 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
831
832 clientSSL = Connection(clientContext, client)
833 clientSSL.set_connect_state()
834
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400835 serverContext = Context(TLSv1_METHOD)
836 serverContext.use_certificate(
837 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
838 serverContext.use_privatekey(
839 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
840
841 serverSSL = Connection(serverContext, server)
842 serverSSL.set_accept_state()
843
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400844 # Without load_verify_locations above, the handshake
845 # will fail:
846 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
847 # 'certificate verify failed')]
848 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400849
850 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400851 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400852
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500853
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400854 def test_load_verify_file(self):
855 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900856 :py:obj:`Context.load_verify_locations` accepts a file name and uses the
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400857 certificates within for verification purposes.
858 """
859 cafile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400860 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400861 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400862 fObj.close()
863
864 self._load_verify_locations_test(cafile)
865
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400866
867 def test_load_verify_invalid_file(self):
868 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900869 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when passed a
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400870 non-existent cafile.
871 """
872 clientContext = Context(TLSv1_METHOD)
873 self.assertRaises(
874 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400875
876
877 def test_load_verify_directory(self):
878 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900879 :py:obj:`Context.load_verify_locations` accepts a directory name and uses
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400880 the certificates within for verification purposes.
881 """
882 capath = self.mktemp()
883 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400884 # Hash values computed manually with c_rehash to avoid depending on
885 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
886 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500887 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400888 cafile = join(capath, name)
889 fObj = open(cafile, 'w')
890 fObj.write(cleartextCertificatePEM.decode('ascii'))
891 fObj.close()
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400892
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400893 self._load_verify_locations_test(None, capath)
894
895
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400896 def test_load_verify_locations_wrong_args(self):
897 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900898 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if called with
899 the wrong number of arguments or with non-:py:obj:`str` arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400900 """
901 context = Context(TLSv1_METHOD)
902 self.assertRaises(TypeError, context.load_verify_locations)
903 self.assertRaises(TypeError, context.load_verify_locations, object())
904 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
905 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
906
907
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400908 if platform == "win32":
909 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400910 "See LP#404343 and LP#404344."
911 else:
912 def test_set_default_verify_paths(self):
913 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900914 :py:obj:`Context.set_default_verify_paths` causes the platform-specific CA
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400915 certificate locations to be used for verification purposes.
916 """
917 # Testing this requires a server with a certificate signed by one of
918 # the CAs in the platform CA location. Getting one of those costs
919 # money. Fortunately (or unfortunately, depending on your
920 # perspective), it's easy to think of a public server on the
921 # internet which has such a certificate. Connecting to the network
922 # in a unit test is bad, but it's the only way I can think of to
923 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400924
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400925 # Arg, verisign.com doesn't speak TLSv1
926 context = Context(SSLv3_METHOD)
927 context.set_default_verify_paths()
928 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +0200929 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400930 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400931
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400932 client = socket()
933 client.connect(('verisign.com', 443))
934 clientSSL = Connection(context, client)
935 clientSSL.set_connect_state()
936 clientSSL.do_handshake()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500937 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400938 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400939
940
941 def test_set_default_verify_paths_signature(self):
942 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900943 :py:obj:`Context.set_default_verify_paths` takes no arguments and raises
944 :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400945 """
946 context = Context(TLSv1_METHOD)
947 self.assertRaises(TypeError, context.set_default_verify_paths, None)
948 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
949 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500950
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400951
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500952 def test_add_extra_chain_cert_invalid_cert(self):
953 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900954 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if called with
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500955 other than one argument or if called with an object which is not an
Jonathan Ballet648875f2011-07-16 14:14:58 +0900956 instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500957 """
958 context = Context(TLSv1_METHOD)
959 self.assertRaises(TypeError, context.add_extra_chain_cert)
960 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
961 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
962
963
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400964 def _handshake_test(self, serverContext, clientContext):
965 """
966 Verify that a client and server created with the given contexts can
967 successfully handshake and communicate.
968 """
969 serverSocket, clientSocket = socket_pair()
970
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400971 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400972 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400973
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400974 client = Connection(clientContext, clientSocket)
975 client.set_connect_state()
976
977 # Make them talk to each other.
978 # self._interactInMemory(client, server)
979 for i in range(3):
980 for s in [client, server]:
981 try:
982 s.do_handshake()
983 except WantReadError:
984 pass
985
986
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800987 def test_set_verify_callback_exception(self):
988 """
989 If the verify callback passed to :py:obj:`Context.set_verify` raises an
990 exception, verification fails and the exception is propagated to the
991 caller of :py:obj:`Connection.do_handshake`.
992 """
993 serverContext = Context(TLSv1_METHOD)
994 serverContext.use_privatekey(
995 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
996 serverContext.use_certificate(
997 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
998
999 clientContext = Context(TLSv1_METHOD)
1000 def verify_callback(*args):
1001 raise Exception("silly verify failure")
1002 clientContext.set_verify(VERIFY_PEER, verify_callback)
1003
1004 exc = self.assertRaises(
1005 Exception, self._handshake_test, serverContext, clientContext)
1006 self.assertEqual("silly verify failure", str(exc))
1007
1008
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001009 def test_add_extra_chain_cert(self):
1010 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001011 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509` instance to add to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001012 the certificate chain.
1013
Jonathan Ballet648875f2011-07-16 14:14:58 +09001014 See :py:obj:`_create_certificate_chain` for the details of the certificate
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001015 chain tested.
1016
1017 The chain is tested by starting a server with scert and connecting
1018 to it with a client which trusts cacert and requires verification to
1019 succeed.
1020 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001021 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001022 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1023
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001024 # Dump the CA certificate to a file because that's the only way to load
1025 # it as a trusted CA in the client context.
1026 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001027 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001028 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001029 fObj.close()
1030
1031 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001032 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001033 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001034 fObj.close()
1035
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001036 # Create the server context
1037 serverContext = Context(TLSv1_METHOD)
1038 serverContext.use_privatekey(skey)
1039 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001040 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001041 serverContext.add_extra_chain_cert(icert)
1042
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001043 # Create the client
1044 clientContext = Context(TLSv1_METHOD)
1045 clientContext.set_verify(
1046 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001047 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001048
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001049 # Try it out.
1050 self._handshake_test(serverContext, clientContext)
1051
1052
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001053 def test_use_certificate_chain_file(self):
1054 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001055 :py:obj:`Context.use_certificate_chain_file` reads a certificate chain from
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001056 the specified file.
1057
1058 The chain is tested by starting a server with scert and connecting
1059 to it with a client which trusts cacert and requires verification to
1060 succeed.
1061 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001062 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001063 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1064
1065 # Write out the chain file.
1066 chainFile = self.mktemp()
Jean-Paul Calderoned8607982014-01-18 10:30:55 -05001067 fObj = open(chainFile, 'wb')
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001068 # Most specific to least general.
Jean-Paul Calderoned8607982014-01-18 10:30:55 -05001069 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1070 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1071 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001072 fObj.close()
1073
1074 serverContext = Context(TLSv1_METHOD)
1075 serverContext.use_certificate_chain_file(chainFile)
1076 serverContext.use_privatekey(skey)
1077
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001078 fObj = open('ca.pem', 'w')
1079 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001080 fObj.close()
1081
1082 clientContext = Context(TLSv1_METHOD)
1083 clientContext.set_verify(
1084 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001085 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001086
1087 self._handshake_test(serverContext, clientContext)
1088
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001089
1090 def test_use_certificate_chain_file_wrong_args(self):
1091 """
1092 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1093 if passed zero or more than one argument or when passed a non-byte
1094 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error` when
1095 passed a bad chain file name (for example, the name of a file which does
1096 not exist).
1097 """
1098 context = Context(TLSv1_METHOD)
1099 self.assertRaises(TypeError, context.use_certificate_chain_file)
1100 self.assertRaises(TypeError, context.use_certificate_chain_file, object())
1101 self.assertRaises(TypeError, context.use_certificate_chain_file, b"foo", object())
1102
1103 self.assertRaises(Error, context.use_certificate_chain_file, self.mktemp())
1104
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001105 # XXX load_client_ca
1106 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001107
1108 def test_get_verify_mode_wrong_args(self):
1109 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001110 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001111 arguments.
1112 """
1113 context = Context(TLSv1_METHOD)
1114 self.assertRaises(TypeError, context.get_verify_mode, None)
1115
1116
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001117 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001118 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001119 :py:obj:`Context.get_verify_mode` returns the verify mode flags previously
1120 passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001121 """
1122 context = Context(TLSv1_METHOD)
1123 self.assertEquals(context.get_verify_mode(), 0)
1124 context.set_verify(
1125 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1126 self.assertEquals(
1127 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1128
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001129
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001130 if not PY3:
1131 def test_set_verify_mode_long(self):
1132 """
1133 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1134 type :py:obj:`long` as well as :py:obj:`int`.
1135 """
1136 context = Context(TLSv1_METHOD)
1137 self.assertEquals(context.get_verify_mode(), 0)
1138 context.set_verify(
1139 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None)
1140 self.assertEquals(
1141 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1142
1143
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001144 def test_load_tmp_dh_wrong_args(self):
1145 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001146 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
1147 number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001148 """
1149 context = Context(TLSv1_METHOD)
1150 self.assertRaises(TypeError, context.load_tmp_dh)
1151 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1152 self.assertRaises(TypeError, context.load_tmp_dh, object())
1153
1154
1155 def test_load_tmp_dh_missing_file(self):
1156 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001157 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the specified file
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001158 does not exist.
1159 """
1160 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001161 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001162
1163
1164 def test_load_tmp_dh(self):
1165 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001166 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001167 specified file.
1168 """
1169 context = Context(TLSv1_METHOD)
1170 dhfilename = self.mktemp()
1171 dhfile = open(dhfilename, "w")
1172 dhfile.write(dhparam)
1173 dhfile.close()
1174 context.load_tmp_dh(dhfilename)
1175 # XXX What should I assert here? -exarkun
1176
1177
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001178 def test_set_tmp_ecdh_curve(self):
1179 """
Andy Lutomirski61d7d392014-04-04 12:16:56 -07001180 :py:obj:`Context.set_tmp_ecdh_curve` sets the elliptic
1181 curve for Diffie-Hellman to the specified named curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001182 """
1183 context = Context(TLSv1_METHOD)
1184 for curve in ELLIPTIC_CURVE_DESCRIPTIONS.keys():
1185 context.set_tmp_ecdh_curve(curve) # Must not throw.
1186
Laurens Van Houtvenf5df2432014-04-03 12:17:28 +02001187
Andy Lutomirski61d7d392014-04-04 12:16:56 -07001188 def test_set_tmp_ecdh_curve_bad_sn(self):
1189 """
1190 :py:obj:`Context.set_tmp_ecdh_curve` raises
1191 :py:obj:`UnknownObject` if passed a curve_name that OpenSSL
1192 does not recognize and EC is available. It raises
1193 :py:obj:`ECNotAvailable` if EC is not available at all.
1194 """
1195 context = Context(TLSv1_METHOD)
1196 try:
1197 context.set_tmp_ecdh_curve('not_an_elliptic_curve')
1198 except ECNotAvailable:
1199 self.assertFalse(_Cryptography_HAS_EC)
1200 except UnknownObject:
1201 self.assertTrue(_Cryptography_HAS_EC)
1202 else:
1203 self.assertFalse(True)
1204
1205
1206 def test_set_tmp_ecdh_curve_not_a_curve(self):
1207 """
1208 :py:obj:`Context.set_tmp_ecdh_curve` raises
1209 :py:obj:`UnsupportedEllipticCurve` if passed a curve_name that
1210 OpenSSL cannot instantiate as an elliptic curve. It raises
1211 :py:obj:`ECNotAvailable` if EC is not available at all.
1212 """
1213 context = Context(TLSv1_METHOD)
1214 try:
1215 context.set_tmp_ecdh_curve('sha256')
1216 except ECNotAvailable:
1217 self.assertFalse(_Cryptography_HAS_EC)
1218 except UnknownObject:
1219 self.assertTrue(_Cryptography_HAS_EC)
1220 else:
1221 self.assertFalse(True)
1222
1223
Laurens Van Houtvenf5df2432014-04-03 12:17:28 +02001224 def test_has_curve_descriptions(self):
1225 """
1226 If the underlying cryptography bindings claim to have elliptic
1227 curve support, there should be at least one curve.
1228
1229 (In theory there could be an OpenSSL that violates this
1230 assumption. If so, this test will fail and we'll find out.)
1231
1232 """
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001233 if _Cryptography_HAS_EC:
Laurens Van Houtvenf5df2432014-04-03 12:17:28 +02001234 self.assertNotEqual(len(ELLIPTIC_CURVE_DESCRIPTIONS), 0)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001235
1236
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001237 def test_set_cipher_list_bytes(self):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001238 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001239 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
1240 ciphers which connections created with the context object will be able
1241 to choose from.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001242 """
1243 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001244 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001245 conn = Connection(context, None)
1246 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001247
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001248
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001249 def test_set_cipher_list_text(self):
1250 """
1251 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
1252 the ciphers which connections created with the context object will be
1253 able to choose from.
1254 """
1255 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -05001256 context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001257 conn = Connection(context, None)
1258 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
1259
1260
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001261 def test_set_cipher_list_wrong_args(self):
1262 """
Jean-Paul Calderone17044832014-01-18 10:20:11 -05001263 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
1264 passed zero arguments or more than one argument or when passed a
1265 non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001266 passed an incorrect cipher list string.
1267 """
1268 context = Context(TLSv1_METHOD)
1269 self.assertRaises(TypeError, context.set_cipher_list)
1270 self.assertRaises(TypeError, context.set_cipher_list, object())
1271 self.assertRaises(TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object())
1272
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001273 self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001274
1275
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001276 def test_set_session_cache_mode_wrong_args(self):
1277 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001278 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1279 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001280 """
1281 context = Context(TLSv1_METHOD)
1282 self.assertRaises(TypeError, context.set_session_cache_mode)
1283 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1284
1285
1286 def test_get_session_cache_mode_wrong_args(self):
1287 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001288 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1289 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001290 """
1291 context = Context(TLSv1_METHOD)
1292 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1293
1294
1295 def test_session_cache_mode(self):
1296 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001297 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1298 cached. The setting can be retrieved via
1299 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001300 """
1301 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001302 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001303 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1304 self.assertEqual(SESS_CACHE_OFF, off)
1305 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1306
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001307 if not PY3:
1308 def test_session_cache_mode_long(self):
1309 """
1310 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1311 of type :py:obj:`long` as well as :py:obj:`int`.
1312 """
1313 context = Context(TLSv1_METHOD)
1314 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1315 self.assertEqual(
1316 SESS_CACHE_BOTH, context.get_session_cache_mode())
1317
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001318
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001319 def test_get_cert_store(self):
1320 """
1321 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store` instance.
1322 """
1323 context = Context(TLSv1_METHOD)
1324 store = context.get_cert_store()
1325 self.assertIsInstance(store, X509Store)
1326
1327
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001328
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001329class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1330 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001331 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
1332 :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001333 """
1334 def test_wrong_args(self):
1335 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001336 :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001337 with other than one argument.
1338 """
1339 context = Context(TLSv1_METHOD)
1340 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1341 self.assertRaises(
1342 TypeError, context.set_tlsext_servername_callback, 1, 2)
1343
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001344
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001345 def test_old_callback_forgotten(self):
1346 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001347 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001348 callback, the one it replaces is dereferenced.
1349 """
1350 def callback(connection):
1351 pass
1352
1353 def replacement(connection):
1354 pass
1355
1356 context = Context(TLSv1_METHOD)
1357 context.set_tlsext_servername_callback(callback)
1358
1359 tracker = ref(callback)
1360 del callback
1361
1362 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001363
1364 # One run of the garbage collector happens to work on CPython. PyPy
1365 # doesn't collect the underlying object until a second run for whatever
1366 # reason. That's fine, it still demonstrates our code has properly
1367 # dropped the reference.
1368 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001369 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001370
1371 callback = tracker()
1372 if callback is not None:
1373 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001374 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001375 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001376
1377
1378 def test_no_servername(self):
1379 """
1380 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001381 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
1382 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001383 """
1384 args = []
1385 def servername(conn):
1386 args.append((conn, conn.get_servername()))
1387 context = Context(TLSv1_METHOD)
1388 context.set_tlsext_servername_callback(servername)
1389
1390 # Lose our reference to it. The Context is responsible for keeping it
1391 # alive now.
1392 del servername
1393 collect()
1394
1395 # Necessary to actually accept the connection
1396 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1397 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1398
1399 # Do a little connection to trigger the logic
1400 server = Connection(context, None)
1401 server.set_accept_state()
1402
1403 client = Connection(Context(TLSv1_METHOD), None)
1404 client.set_connect_state()
1405
1406 self._interactInMemory(server, client)
1407
1408 self.assertEqual([(server, None)], args)
1409
1410
1411 def test_servername(self):
1412 """
1413 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +09001414 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
1415 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001416 """
1417 args = []
1418 def servername(conn):
1419 args.append((conn, conn.get_servername()))
1420 context = Context(TLSv1_METHOD)
1421 context.set_tlsext_servername_callback(servername)
1422
1423 # Necessary to actually accept the connection
1424 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1425 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1426
1427 # Do a little connection to trigger the logic
1428 server = Connection(context, None)
1429 server.set_accept_state()
1430
1431 client = Connection(Context(TLSv1_METHOD), None)
1432 client.set_connect_state()
1433 client.set_tlsext_host_name(b("foo1.example.com"))
1434
1435 self._interactInMemory(server, client)
1436
1437 self.assertEqual([(server, b("foo1.example.com"))], args)
1438
1439
1440
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001441class SessionTests(TestCase):
1442 """
1443 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1444 """
1445 def test_construction(self):
1446 """
1447 :py:class:`Session` can be constructed with no arguments, creating a new
1448 instance of that type.
1449 """
1450 new_session = Session()
1451 self.assertTrue(isinstance(new_session, Session))
1452
1453
1454 def test_construction_wrong_args(self):
1455 """
1456 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
1457 is raised.
1458 """
1459 self.assertRaises(TypeError, Session, 123)
1460 self.assertRaises(TypeError, Session, "hello")
1461 self.assertRaises(TypeError, Session, object())
1462
1463
1464
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001465class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05001466 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001467 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001468 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001469 # XXX get_peer_certificate -> None
1470 # XXX sock_shutdown
1471 # XXX master_key -> TypeError
1472 # XXX server_random -> TypeError
1473 # XXX state_string
1474 # XXX connect -> TypeError
1475 # XXX connect_ex -> TypeError
1476 # XXX set_connect_state -> TypeError
1477 # XXX set_accept_state -> TypeError
1478 # XXX renegotiate_pending
1479 # XXX do_handshake -> TypeError
1480 # XXX bio_read -> TypeError
1481 # XXX recv -> TypeError
1482 # XXX send -> TypeError
1483 # XXX bio_write -> TypeError
1484
Rick Deane15b1472009-07-09 15:53:42 -05001485 def test_type(self):
1486 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001487 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001488 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05001489 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001490 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05001491 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001492 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05001493
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001494
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001495 def test_get_context(self):
1496 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001497 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
1498 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001499 """
1500 context = Context(TLSv1_METHOD)
1501 connection = Connection(context, None)
1502 self.assertIdentical(connection.get_context(), context)
1503
1504
1505 def test_get_context_wrong_args(self):
1506 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001507 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001508 arguments.
1509 """
1510 connection = Connection(Context(TLSv1_METHOD), None)
1511 self.assertRaises(TypeError, connection.get_context, None)
1512
1513
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001514 def test_set_context_wrong_args(self):
1515 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001516 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
1517 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001518 than 1.
1519 """
1520 ctx = Context(TLSv1_METHOD)
1521 connection = Connection(ctx, None)
1522 self.assertRaises(TypeError, connection.set_context)
1523 self.assertRaises(TypeError, connection.set_context, object())
1524 self.assertRaises(TypeError, connection.set_context, "hello")
1525 self.assertRaises(TypeError, connection.set_context, 1)
1526 self.assertRaises(TypeError, connection.set_context, 1, 2)
1527 self.assertRaises(
1528 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
1529 self.assertIdentical(ctx, connection.get_context())
1530
1531
1532 def test_set_context(self):
1533 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001534 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001535 for the connection.
1536 """
1537 original = Context(SSLv23_METHOD)
1538 replacement = Context(TLSv1_METHOD)
1539 connection = Connection(original, None)
1540 connection.set_context(replacement)
1541 self.assertIdentical(replacement, connection.get_context())
1542 # Lose our references to the contexts, just in case the Connection isn't
1543 # properly managing its own contributions to their reference counts.
1544 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001545 collect()
1546
1547
1548 def test_set_tlsext_host_name_wrong_args(self):
1549 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001550 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001551 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09001552 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001553 """
1554 conn = Connection(Context(TLSv1_METHOD), None)
1555 self.assertRaises(TypeError, conn.set_tlsext_host_name)
1556 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
1557 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
1558 self.assertRaises(
1559 TypeError, conn.set_tlsext_host_name, b("with\0null"))
1560
1561 if version_info >= (3,):
1562 # On Python 3.x, don't accidentally implicitly convert from text.
1563 self.assertRaises(
1564 TypeError,
1565 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001566
1567
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001568 def test_get_servername_wrong_args(self):
1569 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001570 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001571 arguments.
1572 """
1573 connection = Connection(Context(TLSv1_METHOD), None)
1574 self.assertRaises(TypeError, connection.get_servername, object())
1575 self.assertRaises(TypeError, connection.get_servername, 1)
1576 self.assertRaises(TypeError, connection.get_servername, "hello")
1577
1578
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001579 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001580 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001581 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001582 immediate read.
1583 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001584 connection = Connection(Context(TLSv1_METHOD), None)
1585 self.assertEquals(connection.pending(), 0)
1586
1587
1588 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001589 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001590 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001591 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001592 connection = Connection(Context(TLSv1_METHOD), None)
1593 self.assertRaises(TypeError, connection.pending, None)
1594
1595
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001596 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001597 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001598 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001599 argument or with the wrong number of arguments.
1600 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001601 connection = Connection(Context(TLSv1_METHOD), socket())
1602 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001603 self.assertRaises(TypeError, connection.connect)
1604 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001605
1606
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001607 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001608 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001609 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001610 connect method raises it.
1611 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001612 client = socket()
1613 context = Context(TLSv1_METHOD)
1614 clientSSL = Connection(context, client)
1615 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04001616 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001617
1618
1619 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001620 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001621 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001622 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001623 port = socket()
1624 port.bind(('', 0))
1625 port.listen(3)
1626
1627 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001628 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
1629 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001630
1631
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001632 if platform == "darwin":
1633 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
1634 else:
1635 def test_connect_ex(self):
1636 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001637 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001638 errno instead of raising an exception.
1639 """
1640 port = socket()
1641 port.bind(('', 0))
1642 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001643
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001644 clientSSL = Connection(Context(TLSv1_METHOD), socket())
1645 clientSSL.setblocking(False)
1646 result = clientSSL.connect_ex(port.getsockname())
1647 expected = (EINPROGRESS, EWOULDBLOCK)
1648 self.assertTrue(
1649 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001650
1651
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001652 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001653 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001654 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001655 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001656 connection = Connection(Context(TLSv1_METHOD), socket())
1657 self.assertRaises(TypeError, connection.accept, None)
1658
1659
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001660 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001661 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001662 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
1663 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001664 connection originated from.
1665 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001666 ctx = Context(TLSv1_METHOD)
1667 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1668 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001669 port = socket()
1670 portSSL = Connection(ctx, port)
1671 portSSL.bind(('', 0))
1672 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001673
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001674 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001675
1676 # Calling portSSL.getsockname() here to get the server IP address sounds
1677 # great, but frequently fails on Windows.
1678 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001679
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001680 serverSSL, address = portSSL.accept()
1681
1682 self.assertTrue(isinstance(serverSSL, Connection))
1683 self.assertIdentical(serverSSL.get_context(), ctx)
1684 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001685
1686
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001687 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001688 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001689 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001690 number of arguments or with arguments other than integers.
1691 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001692 connection = Connection(Context(TLSv1_METHOD), None)
1693 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04001694 self.assertRaises(TypeError, connection.get_shutdown, None)
1695 self.assertRaises(TypeError, connection.set_shutdown)
1696 self.assertRaises(TypeError, connection.set_shutdown, None)
1697 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001698
1699
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001700 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001701 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001702 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001703 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001704 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001705 self.assertFalse(server.shutdown())
1706 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001707 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001708 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
1709 client.shutdown()
1710 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
1711 self.assertRaises(ZeroReturnError, server.recv, 1024)
1712 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001713
1714
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001715 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001716 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001717 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001718 process.
1719 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001720 connection = Connection(Context(TLSv1_METHOD), socket())
1721 connection.set_shutdown(RECEIVED_SHUTDOWN)
1722 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1723
1724
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05001725 if not PY3:
1726 def test_set_shutdown_long(self):
1727 """
1728 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
1729 of type :py:obj:`long` as well as :py:obj:`int`.
1730 """
1731 connection = Connection(Context(TLSv1_METHOD), socket())
1732 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
1733 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1734
1735
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001736 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001737 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001738 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
1739 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001740 with any arguments.
1741 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001742 conn = Connection(Context(TLSv1_METHOD), None)
1743 self.assertRaises(TypeError, conn.get_app_data, None)
1744 self.assertRaises(TypeError, conn.set_app_data)
1745 self.assertRaises(TypeError, conn.set_app_data, None, None)
1746
1747
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001748 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001749 """
1750 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001751 :py:obj:`Connection.set_app_data` and later retrieved with
1752 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001753 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001754 conn = Connection(Context(TLSv1_METHOD), None)
1755 app_data = object()
1756 conn.set_app_data(app_data)
1757 self.assertIdentical(conn.get_app_data(), app_data)
1758
1759
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001760 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001761 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001762 :py:obj:`Connection.makefile` is not implemented and calling that method raises
1763 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001764 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001765 conn = Connection(Context(TLSv1_METHOD), None)
1766 self.assertRaises(NotImplementedError, conn.makefile)
1767
1768
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001769 def test_get_peer_cert_chain_wrong_args(self):
1770 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001771 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001772 arguments.
1773 """
1774 conn = Connection(Context(TLSv1_METHOD), None)
1775 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
1776 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
1777 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
1778 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
1779
1780
1781 def test_get_peer_cert_chain(self):
1782 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001783 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001784 the connected server returned for the certification verification.
1785 """
1786 chain = _create_certificate_chain()
1787 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1788
1789 serverContext = Context(TLSv1_METHOD)
1790 serverContext.use_privatekey(skey)
1791 serverContext.use_certificate(scert)
1792 serverContext.add_extra_chain_cert(icert)
1793 serverContext.add_extra_chain_cert(cacert)
1794 server = Connection(serverContext, None)
1795 server.set_accept_state()
1796
1797 # Create the client
1798 clientContext = Context(TLSv1_METHOD)
1799 clientContext.set_verify(VERIFY_NONE, verify_cb)
1800 client = Connection(clientContext, None)
1801 client.set_connect_state()
1802
1803 self._interactInMemory(client, server)
1804
1805 chain = client.get_peer_cert_chain()
1806 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001807 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001808 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001809 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001810 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001811 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001812 "Authority Certificate", chain[2].get_subject().CN)
1813
1814
1815 def test_get_peer_cert_chain_none(self):
1816 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001817 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001818 certificate chain.
1819 """
1820 ctx = Context(TLSv1_METHOD)
1821 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1822 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1823 server = Connection(ctx, None)
1824 server.set_accept_state()
1825 client = Connection(Context(TLSv1_METHOD), None)
1826 client.set_connect_state()
1827 self._interactInMemory(client, server)
1828 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001829
1830
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001831 def test_get_session_wrong_args(self):
1832 """
1833 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
1834 with any arguments.
1835 """
1836 ctx = Context(TLSv1_METHOD)
1837 server = Connection(ctx, None)
1838 self.assertRaises(TypeError, server.get_session, 123)
1839 self.assertRaises(TypeError, server.get_session, "hello")
1840 self.assertRaises(TypeError, server.get_session, object())
1841
1842
1843 def test_get_session_unconnected(self):
1844 """
1845 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
1846 an object which has not been connected.
1847 """
1848 ctx = Context(TLSv1_METHOD)
1849 server = Connection(ctx, None)
1850 session = server.get_session()
1851 self.assertIdentical(None, session)
1852
1853
1854 def test_server_get_session(self):
1855 """
1856 On the server side of a connection, :py:obj:`Connection.get_session`
1857 returns a :py:class:`Session` instance representing the SSL session for
1858 that connection.
1859 """
1860 server, client = self._loopback()
1861 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001862 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001863
1864
1865 def test_client_get_session(self):
1866 """
1867 On the client side of a connection, :py:obj:`Connection.get_session`
1868 returns a :py:class:`Session` instance representing the SSL session for
1869 that connection.
1870 """
1871 server, client = self._loopback()
1872 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001873 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001874
1875
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05001876 def test_set_session_wrong_args(self):
1877 """
1878 If called with an object that is not an instance of :py:class:`Session`,
1879 or with other than one argument, :py:obj:`Connection.set_session` raises
1880 :py:obj:`TypeError`.
1881 """
1882 ctx = Context(TLSv1_METHOD)
1883 connection = Connection(ctx, None)
1884 self.assertRaises(TypeError, connection.set_session)
1885 self.assertRaises(TypeError, connection.set_session, 123)
1886 self.assertRaises(TypeError, connection.set_session, "hello")
1887 self.assertRaises(TypeError, connection.set_session, object())
1888 self.assertRaises(
1889 TypeError, connection.set_session, Session(), Session())
1890
1891
1892 def test_client_set_session(self):
1893 """
1894 :py:obj:`Connection.set_session`, when used prior to a connection being
1895 established, accepts a :py:class:`Session` instance and causes an
1896 attempt to re-use the session it represents when the SSL handshake is
1897 performed.
1898 """
1899 key = load_privatekey(FILETYPE_PEM, server_key_pem)
1900 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
1901 ctx = Context(TLSv1_METHOD)
1902 ctx.use_privatekey(key)
1903 ctx.use_certificate(cert)
1904 ctx.set_session_id("unity-test")
1905
1906 def makeServer(socket):
1907 server = Connection(ctx, socket)
1908 server.set_accept_state()
1909 return server
1910
1911 originalServer, originalClient = self._loopback(
1912 serverFactory=makeServer)
1913 originalSession = originalClient.get_session()
1914
1915 def makeClient(socket):
1916 client = self._loopbackClientFactory(socket)
1917 client.set_session(originalSession)
1918 return client
1919 resumedServer, resumedClient = self._loopback(
1920 serverFactory=makeServer,
1921 clientFactory=makeClient)
1922
1923 # This is a proxy: in general, we have no access to any unique
1924 # identifier for the session (new enough versions of OpenSSL expose a
1925 # hash which could be usable, but "new enough" is very, very new).
1926 # Instead, exploit the fact that the master key is re-used if the
1927 # session is re-used. As long as the master key for the two connections
1928 # is the same, the session was re-used!
1929 self.assertEqual(
1930 originalServer.master_key(), resumedServer.master_key())
1931
1932
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05001933 def test_set_session_wrong_method(self):
1934 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05001935 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
1936 instance associated with a context using a different SSL method than the
1937 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
1938 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05001939 """
1940 key = load_privatekey(FILETYPE_PEM, server_key_pem)
1941 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
1942 ctx = Context(TLSv1_METHOD)
1943 ctx.use_privatekey(key)
1944 ctx.use_certificate(cert)
1945 ctx.set_session_id("unity-test")
1946
1947 def makeServer(socket):
1948 server = Connection(ctx, socket)
1949 server.set_accept_state()
1950 return server
1951
1952 originalServer, originalClient = self._loopback(
1953 serverFactory=makeServer)
1954 originalSession = originalClient.get_session()
1955
1956 def makeClient(socket):
1957 # Intentionally use a different, incompatible method here.
1958 client = Connection(Context(SSLv3_METHOD), socket)
1959 client.set_connect_state()
1960 client.set_session(originalSession)
1961 return client
1962
1963 self.assertRaises(
1964 Error,
1965 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
1966
1967
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07001968 def test_wantWriteError(self):
1969 """
1970 :py:obj:`Connection` methods which generate output raise
1971 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
1972 fail indicating a should-write state.
1973 """
1974 client_socket, server_socket = socket_pair()
1975 # Fill up the client's send buffer so Connection won't be able to write
1976 # anything.
Jean-Paul Calderone7d7c9c22014-02-18 16:38:26 -05001977 msg = b"x" * 512
Jean-Paul Calderone22c28b42014-02-18 16:40:34 -05001978 for i in range(2048):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07001979 try:
1980 client_socket.send(msg)
1981 except error as e:
1982 if e.errno == EWOULDBLOCK:
1983 break
1984 raise
1985 else:
1986 self.fail(
1987 "Failed to fill socket buffer, cannot test BIO want write")
1988
1989 ctx = Context(TLSv1_METHOD)
1990 conn = Connection(ctx, client_socket)
1991 # Client's speak first, so make it an SSL client
1992 conn.set_connect_state()
1993 self.assertRaises(WantWriteError, conn.do_handshake)
1994
1995 # XXX want_read
1996
Fedor Brunner416f4a12014-03-28 13:18:38 +01001997 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01001998 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04001999 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2000 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002001 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002002 ctx = Context(TLSv1_METHOD)
2003 connection = Connection(ctx, None)
2004 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002005
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002006
Fedor Brunner416f4a12014-03-28 13:18:38 +01002007 def test_get_peer_finished_before_connect(self):
2008 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002009 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2010 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002011 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002012 ctx = Context(TLSv1_METHOD)
2013 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002014 self.assertEqual(connection.get_peer_finished(), None)
2015
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002016
Fedor Brunner416f4a12014-03-28 13:18:38 +01002017 def test_get_finished(self):
2018 """
2019 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002020 message send from client, or server. Finished messages are send during
2021 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002022 """
2023
Fedor Brunner5747b932014-03-05 14:22:34 +01002024 server, client = self._loopback()
2025
2026 self.assertNotEqual(server.get_finished(), None)
2027 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002028
Jean-Paul Calderoned979f232014-03-30 11:58:00 -04002029
Fedor Brunner416f4a12014-03-28 13:18:38 +01002030 def test_get_peer_finished(self):
2031 """
2032 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002033 message received from client, or server. Finished messages are send
2034 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002035 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002036 server, client = self._loopback()
2037
2038 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002039 self.assertTrue(len(server.get_peer_finished()) > 0)
2040
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002041
Fedor Brunner416f4a12014-03-28 13:18:38 +01002042 def test_tls_finished_message_symmetry(self):
2043 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002044 The TLS Finished message send by server must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002045 received by client.
2046
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002047 The TLS Finished message send by client must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002048 received by server.
2049 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002050 server, client = self._loopback()
2051
Fedor Brunner5747b932014-03-05 14:22:34 +01002052 self.assertEqual(server.get_finished(), client.get_peer_finished())
2053 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002054
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002055
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002056 def test_get_cipher_name_before_connect(self):
2057 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002058 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2059 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002060 """
2061 ctx = Context(TLSv1_METHOD)
2062 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002063 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002064
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002065
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002066 def test_get_cipher_name(self):
2067 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002068 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2069 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002070 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002071 server, client = self._loopback()
2072 server_cipher_name, client_cipher_name = \
2073 server.get_cipher_name(), client.get_cipher_name()
2074
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002075 self.assertIsInstance(server_cipher_name, text_type)
2076 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002077
2078 self.assertEqual(server_cipher_name, client_cipher_name)
2079
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002080
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002081 def test_get_cipher_version_before_connect(self):
2082 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002083 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2084 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002085 """
2086 ctx = Context(TLSv1_METHOD)
2087 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002088 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002089
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002090
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002091 def test_get_cipher_version(self):
2092 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002093 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2094 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002095 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002096 server, client = self._loopback()
2097 server_cipher_version, client_cipher_version = \
2098 server.get_cipher_version(), client.get_cipher_version()
2099
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002100 self.assertIsInstance(server_cipher_version, text_type)
2101 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002102
2103 self.assertEqual(server_cipher_version, client_cipher_version)
2104
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002105
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002106 def test_get_cipher_bits_before_connect(self):
2107 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002108 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2109 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002110 """
2111 ctx = Context(TLSv1_METHOD)
2112 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002113 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002114
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002115
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002116 def test_get_cipher_bits(self):
2117 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002118 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2119 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002120 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002121 server, client = self._loopback()
2122 server_cipher_bits, client_cipher_bits = \
2123 server.get_cipher_bits(), client.get_cipher_bits()
2124
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002125 self.assertIsInstance(server_cipher_bits, int)
2126 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002127
2128 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002129
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002130
2131
2132class ConnectionGetCipherListTests(TestCase):
2133 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002134 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002135 """
2136 def test_wrong_args(self):
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002137 """
2138 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
2139 arguments.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002140 """
2141 connection = Connection(Context(TLSv1_METHOD), None)
2142 self.assertRaises(TypeError, connection.get_cipher_list, None)
2143
Jonathan Ballet648875f2011-07-16 14:14:58 +09002144
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002145 def test_result(self):
2146 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002147 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2148 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002149 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002150 connection = Connection(Context(TLSv1_METHOD), None)
2151 ciphers = connection.get_cipher_list()
2152 self.assertTrue(isinstance(ciphers, list))
2153 for cipher in ciphers:
2154 self.assertTrue(isinstance(cipher, str))
2155
2156
2157
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002158class ConnectionSendTests(TestCase, _LoopbackMixin):
2159 """
2160 Tests for :py:obj:`Connection.send`
2161 """
2162 def test_wrong_args(self):
2163 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002164 When called with arguments other than string argument for its first
2165 parameter or more than two arguments, :py:obj:`Connection.send` raises
2166 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002167 """
2168 connection = Connection(Context(TLSv1_METHOD), None)
2169 self.assertRaises(TypeError, connection.send)
2170 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002171 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002172
2173
2174 def test_short_bytes(self):
2175 """
2176 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
2177 and returns the number of bytes sent.
2178 """
2179 server, client = self._loopback()
2180 count = server.send(b('xy'))
2181 self.assertEquals(count, 2)
2182 self.assertEquals(client.recv(2), b('xy'))
2183
2184 try:
2185 memoryview
2186 except NameError:
2187 "cannot test sending memoryview without memoryview"
2188 else:
2189 def test_short_memoryview(self):
2190 """
2191 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002192 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002193 bytes sent.
2194 """
2195 server, client = self._loopback()
2196 count = server.send(memoryview(b('xy')))
2197 self.assertEquals(count, 2)
2198 self.assertEquals(client.recv(2), b('xy'))
2199
2200
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002201
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002202class ConnectionSendallTests(TestCase, _LoopbackMixin):
2203 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002204 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002205 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002206 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002207 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002208 When called with arguments other than a string argument for its first
2209 parameter or with more than two arguments, :py:obj:`Connection.sendall`
2210 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002211 """
2212 connection = Connection(Context(TLSv1_METHOD), None)
2213 self.assertRaises(TypeError, connection.sendall)
2214 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002215 self.assertRaises(
2216 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002217
2218
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002219 def test_short(self):
2220 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002221 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002222 it.
2223 """
2224 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04002225 server.sendall(b('x'))
2226 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002227
2228
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002229 try:
2230 memoryview
2231 except NameError:
2232 "cannot test sending memoryview without memoryview"
2233 else:
2234 def test_short_memoryview(self):
2235 """
2236 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002237 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002238 """
2239 server, client = self._loopback()
2240 server.sendall(memoryview(b('x')))
2241 self.assertEquals(client.recv(1), b('x'))
2242
2243
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002244 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002245 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002246 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002247 it even if this requires multiple calls of an underlying write function.
2248 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002249 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04002250 # Should be enough, underlying SSL_write should only do 16k at a time.
2251 # On Windows, after 32k of bytes the write will block (forever - because
2252 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04002253 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002254 server.sendall(message)
2255 accum = []
2256 received = 0
2257 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04002258 data = client.recv(1024)
2259 accum.append(data)
2260 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04002261 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002262
2263
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002264 def test_closed(self):
2265 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002266 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002267 write error from the low level write call.
2268 """
2269 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04002270 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002271 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02002272 if platform == "win32":
2273 self.assertEqual(exc.args[0], ESHUTDOWN)
2274 else:
2275 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002276
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002277
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002278
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002279class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
2280 """
2281 Tests for SSL renegotiation APIs.
2282 """
2283 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002284 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002285 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002286 arguments.
2287 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002288 connection = Connection(Context(TLSv1_METHOD), None)
2289 self.assertRaises(TypeError, connection.renegotiate, None)
2290
2291
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002292 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002293 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002294 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002295 any arguments.
2296 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002297 connection = Connection(Context(TLSv1_METHOD), None)
2298 self.assertRaises(TypeError, connection.total_renegotiations, None)
2299
2300
2301 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002302 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002303 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002304 renegotiations have happened.
2305 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002306 connection = Connection(Context(TLSv1_METHOD), None)
2307 self.assertEquals(connection.total_renegotiations(), 0)
2308
2309
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002310# def test_renegotiate(self):
2311# """
2312# """
2313# server, client = self._loopback()
2314
2315# server.send("hello world")
2316# self.assertEquals(client.recv(len("hello world")), "hello world")
2317
2318# self.assertEquals(server.total_renegotiations(), 0)
2319# self.assertTrue(server.renegotiate())
2320
2321# server.setblocking(False)
2322# client.setblocking(False)
2323# while server.renegotiate_pending():
2324# client.do_handshake()
2325# server.do_handshake()
2326
2327# self.assertEquals(server.total_renegotiations(), 1)
2328
2329
2330
2331
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002332class ErrorTests(TestCase):
2333 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002334 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002335 """
2336 def test_type(self):
2337 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002338 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002339 """
2340 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05002341 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05002342
2343
2344
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002345class ConstantsTests(TestCase):
2346 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002347 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002348
2349 These are values defined by OpenSSL intended only to be used as flags to
2350 OpenSSL APIs. The only assertions it seems can be made about them is
2351 their values.
2352 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002353 # unittest.TestCase has no skip mechanism
2354 if OP_NO_QUERY_MTU is not None:
2355 def test_op_no_query_mtu(self):
2356 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002357 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002358 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002359 """
2360 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
2361 else:
2362 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002363
2364
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002365 if OP_COOKIE_EXCHANGE is not None:
2366 def test_op_cookie_exchange(self):
2367 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002368 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002369 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002370 """
2371 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
2372 else:
2373 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002374
2375
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002376 if OP_NO_TICKET is not None:
2377 def test_op_no_ticket(self):
2378 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002379 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002380 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002381 """
2382 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04002383 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002384 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05002385
2386
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002387 if OP_NO_COMPRESSION is not None:
2388 def test_op_no_compression(self):
2389 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002390 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
2391 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002392 """
2393 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
2394 else:
2395 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
2396
2397
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002398 def test_sess_cache_off(self):
2399 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002400 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
2401 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002402 """
2403 self.assertEqual(0x0, SESS_CACHE_OFF)
2404
2405
2406 def test_sess_cache_client(self):
2407 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002408 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
2409 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002410 """
2411 self.assertEqual(0x1, SESS_CACHE_CLIENT)
2412
2413
2414 def test_sess_cache_server(self):
2415 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002416 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
2417 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002418 """
2419 self.assertEqual(0x2, SESS_CACHE_SERVER)
2420
2421
2422 def test_sess_cache_both(self):
2423 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002424 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
2425 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002426 """
2427 self.assertEqual(0x3, SESS_CACHE_BOTH)
2428
2429
2430 def test_sess_cache_no_auto_clear(self):
2431 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002432 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
2433 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
2434 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002435 """
2436 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
2437
2438
2439 def test_sess_cache_no_internal_lookup(self):
2440 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002441 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
2442 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
2443 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002444 """
2445 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
2446
2447
2448 def test_sess_cache_no_internal_store(self):
2449 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002450 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
2451 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
2452 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002453 """
2454 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
2455
2456
2457 def test_sess_cache_no_internal(self):
2458 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002459 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
2460 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
2461 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002462 """
2463 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
2464
2465
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04002466
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002467class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05002468 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002469 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05002470 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002471 def _server(self, sock):
2472 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002473 Create a new server-side SSL :py:obj:`Connection` object wrapped around
2474 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002475 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002476 # Create the server side Connection. This is mostly setup boilerplate
2477 # - use TLSv1, use a particular certificate, etc.
2478 server_ctx = Context(TLSv1_METHOD)
2479 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2480 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2481 server_store = server_ctx.get_cert_store()
2482 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2483 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2484 server_ctx.check_privatekey()
2485 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002486 # Here the Connection is actually created. If None is passed as the 2nd
2487 # parameter, it indicates a memory BIO should be created.
2488 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002489 server_conn.set_accept_state()
2490 return server_conn
2491
2492
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002493 def _client(self, sock):
2494 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002495 Create a new client-side SSL :py:obj:`Connection` object wrapped around
2496 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002497 """
2498 # Now create the client side Connection. Similar boilerplate to the
2499 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002500 client_ctx = Context(TLSv1_METHOD)
2501 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2502 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2503 client_store = client_ctx.get_cert_store()
2504 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
2505 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
2506 client_ctx.check_privatekey()
2507 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002508 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002509 client_conn.set_connect_state()
2510 return client_conn
2511
2512
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002513 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002514 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002515 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002516 reading from the output of each and writing those bytes to the input of
2517 the other and in this way establish a connection and exchange
2518 application-level bytes with each other.
2519 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002520 server_conn = self._server(None)
2521 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002522
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002523 # There should be no key or nonces yet.
2524 self.assertIdentical(server_conn.master_key(), None)
2525 self.assertIdentical(server_conn.client_random(), None)
2526 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002527
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002528 # First, the handshake needs to happen. We'll deliver bytes back and
2529 # forth between the client and server until neither of them feels like
2530 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002531 self.assertIdentical(
2532 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002533
2534 # Now that the handshake is done, there should be a key and nonces.
2535 self.assertNotIdentical(server_conn.master_key(), None)
2536 self.assertNotIdentical(server_conn.client_random(), None)
2537 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04002538 self.assertEquals(server_conn.client_random(), client_conn.client_random())
2539 self.assertEquals(server_conn.server_random(), client_conn.server_random())
2540 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
2541 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002542
2543 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002544 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05002545
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002546 server_conn.write(important_message)
2547 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002548 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002549 (client_conn, important_message))
2550
2551 client_conn.write(important_message[::-1])
2552 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002553 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002554 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05002555
2556
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002557 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05002558 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002559 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002560
2561 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09002562 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002563 this test fails, there must be a problem outside the memory BIO
2564 code, as no memory BIO is involved here). Even though this isn't a
2565 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05002566 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04002567 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05002568
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002569 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05002570 client_conn.send(important_message)
2571 msg = server_conn.recv(1024)
2572 self.assertEqual(msg, important_message)
2573
2574 # Again in the other direction, just for fun.
2575 important_message = important_message[::-1]
2576 server_conn.send(important_message)
2577 msg = client_conn.recv(1024)
2578 self.assertEqual(msg, important_message)
2579
2580
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04002581 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05002582 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002583 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
2584 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05002585 """
2586 context = Context(SSLv3_METHOD)
2587 client = socket()
2588 clientSSL = Connection(context, client)
2589 self.assertRaises( TypeError, clientSSL.bio_read, 100)
2590 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04002591 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002592
2593
2594 def test_outgoingOverflow(self):
2595 """
2596 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002597 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002598 returned and that many bytes from the beginning of the input can be
2599 read from the other end of the connection.
2600 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002601 server = self._server(None)
2602 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002603
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002604 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002605
2606 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002607 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002608 # Sanity check. We're trying to test what happens when the entire
2609 # input can't be sent. If the entire input was sent, this test is
2610 # meaningless.
2611 self.assertTrue(sent < size)
2612
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002613 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002614 self.assertIdentical(receiver, server)
2615
2616 # We can rely on all of these bytes being received at once because
2617 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
2618 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002619
2620
2621 def test_shutdown(self):
2622 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002623 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
2624 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002625 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002626 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002627 server.bio_shutdown()
2628 e = self.assertRaises(Error, server.recv, 1024)
2629 # We don't want WantReadError or ZeroReturnError or anything - it's a
2630 # handshake failure.
2631 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002632
2633
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002634 def test_unexpectedEndOfFile(self):
2635 """
2636 If the connection is lost before an orderly SSL shutdown occurs,
2637 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
2638 "Unexpected EOF".
2639 """
2640 server_conn, client_conn = self._loopback()
2641 client_conn.sock_shutdown(SHUT_RDWR)
2642 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
2643 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
2644
2645
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002646 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002647 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002648 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 -04002649
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002650 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002651 before the client and server are connected to each other. This
2652 function should specify a list of CAs for the server to send to the
2653 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09002654 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002655 times.
2656 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002657 server = self._server(None)
2658 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002659 self.assertEqual(client.get_client_ca_list(), [])
2660 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002661 ctx = server.get_context()
2662 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002663 self.assertEqual(client.get_client_ca_list(), [])
2664 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002665 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002666 self.assertEqual(client.get_client_ca_list(), expected)
2667 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002668
2669
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002670 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002671 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002672 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002673 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002674 """
2675 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002676 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
2677 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
2678 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002679
2680
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002681 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002682 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002683 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002684 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09002685 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002686 after the connection is set up.
2687 """
2688 def no_ca(ctx):
2689 ctx.set_client_ca_list([])
2690 return []
2691 self._check_client_ca_list(no_ca)
2692
2693
2694 def test_set_one_ca_list(self):
2695 """
2696 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002697 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002698 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002699 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002700 X509Name after the connection is set up.
2701 """
2702 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2703 cadesc = cacert.get_subject()
2704 def single_ca(ctx):
2705 ctx.set_client_ca_list([cadesc])
2706 return [cadesc]
2707 self._check_client_ca_list(single_ca)
2708
2709
2710 def test_set_multiple_ca_list(self):
2711 """
2712 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002713 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002714 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002715 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002716 X509Names after the connection is set up.
2717 """
2718 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2719 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2720
2721 sedesc = secert.get_subject()
2722 cldesc = clcert.get_subject()
2723
2724 def multiple_ca(ctx):
2725 L = [sedesc, cldesc]
2726 ctx.set_client_ca_list(L)
2727 return L
2728 self._check_client_ca_list(multiple_ca)
2729
2730
2731 def test_reset_ca_list(self):
2732 """
2733 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09002734 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002735 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002736 """
2737 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2738 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2739 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2740
2741 cadesc = cacert.get_subject()
2742 sedesc = secert.get_subject()
2743 cldesc = clcert.get_subject()
2744
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002745 def changed_ca(ctx):
2746 ctx.set_client_ca_list([sedesc, cldesc])
2747 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002748 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002749 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002750
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002751
2752 def test_mutated_ca_list(self):
2753 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002754 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002755 afterwards, this does not affect the list of CA names sent to the
2756 client.
2757 """
2758 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2759 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2760
2761 cadesc = cacert.get_subject()
2762 sedesc = secert.get_subject()
2763
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002764 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002765 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002766 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002767 L.append(sedesc)
2768 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002769 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002770
2771
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002772 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002773 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002774 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002775 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002776 """
2777 ctx = Context(TLSv1_METHOD)
2778 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002779 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002780 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002781 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002782
2783
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002784 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002785 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002786 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09002787 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002788 """
2789 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2790 cadesc = cacert.get_subject()
2791 def single_ca(ctx):
2792 ctx.add_client_ca(cacert)
2793 return [cadesc]
2794 self._check_client_ca_list(single_ca)
2795
2796
2797 def test_multiple_add_client_ca(self):
2798 """
2799 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09002800 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002801 """
2802 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2803 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2804
2805 cadesc = cacert.get_subject()
2806 sedesc = secert.get_subject()
2807
2808 def multiple_ca(ctx):
2809 ctx.add_client_ca(cacert)
2810 ctx.add_client_ca(secert)
2811 return [cadesc, sedesc]
2812 self._check_client_ca_list(multiple_ca)
2813
2814
2815 def test_set_and_add_client_ca(self):
2816 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002817 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
2818 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002819 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002820 """
2821 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2822 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2823 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2824
2825 cadesc = cacert.get_subject()
2826 sedesc = secert.get_subject()
2827 cldesc = clcert.get_subject()
2828
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002829 def mixed_set_add_ca(ctx):
2830 ctx.set_client_ca_list([cadesc, sedesc])
2831 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002832 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002833 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002834
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002835
2836 def test_set_after_add_client_ca(self):
2837 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002838 A call to :py:obj:`Context.set_client_ca_list` after a call to
2839 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002840 call with the names specified by the latter cal.
2841 """
2842 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2843 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2844 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2845
2846 cadesc = cacert.get_subject()
2847 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002848
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002849 def set_replaces_add_ca(ctx):
2850 ctx.add_client_ca(clcert)
2851 ctx.set_client_ca_list([cadesc])
2852 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002853 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002854 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002855
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002856
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002857
2858class ConnectionBIOTests(TestCase):
2859 """
2860 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
2861 """
2862 def test_wantReadError(self):
2863 """
2864 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
2865 if there are no bytes available to be read from the BIO.
2866 """
2867 ctx = Context(TLSv1_METHOD)
2868 conn = Connection(ctx, None)
2869 self.assertRaises(WantReadError, conn.bio_read, 1024)
2870
2871
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002872 def test_buffer_size(self):
2873 """
2874 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
2875 number of bytes to read and return.
2876 """
2877 ctx = Context(TLSv1_METHOD)
2878 conn = Connection(ctx, None)
2879 conn.set_connect_state()
2880 try:
2881 conn.do_handshake()
2882 except WantReadError:
2883 pass
2884 data = conn.bio_read(2)
2885 self.assertEqual(2, len(data))
2886
2887
2888 if not PY3:
2889 def test_buffer_size_long(self):
2890 """
2891 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
2892 :py:obj:`long` as well as :py:obj:`int`.
2893 """
2894 ctx = Context(TLSv1_METHOD)
2895 conn = Connection(ctx, None)
2896 conn.set_connect_state()
2897 try:
2898 conn.do_handshake()
2899 except WantReadError:
2900 pass
2901 data = conn.bio_read(long(2))
2902 self.assertEqual(2, len(data))
2903
2904
2905
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002906
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04002907class InfoConstantTests(TestCase):
2908 """
2909 Tests for assorted constants exposed for use in info callbacks.
2910 """
2911 def test_integers(self):
2912 """
2913 All of the info constants are integers.
2914
2915 This is a very weak test. It would be nice to have one that actually
2916 verifies that as certain info events happen, the value passed to the
2917 info callback matches up with the constant exposed by OpenSSL.SSL.
2918 """
2919 for const in [
2920 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
2921 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
2922 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
2923 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
2924 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
2925 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
2926
2927 self.assertTrue(isinstance(const, int))
2928
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02002929
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002930if __name__ == '__main__':
2931 main()