blob: 83625a7fb977166d0ced5cd276e4816150b440a2 [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
Abraham Martinef063482015-03-25 14:06:24 +000016from warnings import catch_warnings, simplefilter
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050017
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -040018from six import PY3, text_type, u
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050019
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040020from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080021from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040022from OpenSSL.crypto import dump_privatekey, load_privatekey
23from OpenSSL.crypto import dump_certificate, load_certificate
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040024from OpenSSL.crypto import get_elliptic_curves
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040025
Jean-Paul Calderoneb41d1f42014-04-17 16:02:04 -040026from OpenSSL.SSL import _lib
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040027from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
28from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040029from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040030from OpenSSL.SSL import (
31 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
32 TLSv1_1_METHOD, TLSv1_2_METHOD)
33from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040034from OpenSSL.SSL import (
35 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040036
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040037from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050038 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
39 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
40 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
41
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 Calderone6a8cd112014-04-02 21:09:08 -0400283 def _handshakeInMemory(self, client_conn, server_conn):
Jean-Paul Calderoneb2b40782014-05-06 08:47:40 -0400284 """
285 Perform the TLS handshake between two :py:class:`Connection` instances
286 connected to each other via memory BIOs.
287 """
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400288 client_conn.set_connect_state()
289 server_conn.set_accept_state()
290
291 for conn in [client_conn, server_conn]:
292 try:
293 conn.do_handshake()
294 except WantReadError:
295 pass
296
297 self._interactInMemory(client_conn, server_conn)
298
299
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400300
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400301class VersionTests(TestCase):
302 """
303 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900304 :py:obj:`OpenSSL.SSL.SSLeay_version` and
305 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400306 """
307 def test_OPENSSL_VERSION_NUMBER(self):
308 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900309 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400310 byte and the patch, fix, minor, and major versions in the
311 nibbles above that.
312 """
313 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
314
315
316 def test_SSLeay_version(self):
317 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900318 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400319 one of a number of version strings based on that indicator.
320 """
321 versions = {}
322 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
323 SSLEAY_PLATFORM, SSLEAY_DIR]:
324 version = SSLeay_version(t)
325 versions[version] = t
326 self.assertTrue(isinstance(version, bytes))
327 self.assertEqual(len(versions), 5)
328
329
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400330
331class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400332 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900333 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400334 """
335 def test_method(self):
336 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900337 :py:obj:`Context` can be instantiated with one of :py:obj:`SSLv2_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400338 :py:obj:`SSLv3_METHOD`, :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
339 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400340 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400341 methods = [
342 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
343 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400344 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400345
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400346
347 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
348 for meth in maybe:
349 try:
350 Context(meth)
351 except (Error, ValueError):
352 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
353 # don't. Difficult to say in advance.
354 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400355
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400356 self.assertRaises(TypeError, Context, "")
357 self.assertRaises(ValueError, Context, 10)
358
359
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500360 if not PY3:
361 def test_method_long(self):
362 """
363 On Python 2 :py:class:`Context` accepts values of type
364 :py:obj:`long` as well as :py:obj:`int`.
365 """
366 Context(long(TLSv1_METHOD))
367
368
369
Rick Deane15b1472009-07-09 15:53:42 -0500370 def test_type(self):
371 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900372 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400373 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500374 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400375 self.assertIdentical(Context, ContextType)
376 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500377
378
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400379 def test_use_privatekey(self):
380 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900381 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400382 """
383 key = PKey()
384 key.generate_key(TYPE_RSA, 128)
385 ctx = Context(TLSv1_METHOD)
386 ctx.use_privatekey(key)
387 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400388
389
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800390 def test_use_privatekey_file_missing(self):
391 """
392 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error`
393 when passed the name of a file which does not exist.
394 """
395 ctx = Context(TLSv1_METHOD)
396 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
397
398
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500399 if not PY3:
400 def test_use_privatekey_file_long(self):
401 """
402 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
403 filetype of type :py:obj:`long` as well as :py:obj:`int`.
404 """
405 pemfile = self.mktemp()
406
407 key = PKey()
408 key.generate_key(TYPE_RSA, 128)
409
410 with open(pemfile, "wt") as pem:
411 pem.write(
412 dump_privatekey(FILETYPE_PEM, key).decode("ascii"))
413
414 ctx = Context(TLSv1_METHOD)
415 ctx.use_privatekey_file(pemfile, long(FILETYPE_PEM))
416
417
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800418 def test_use_certificate_wrong_args(self):
419 """
420 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
421 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as an
422 argument.
423 """
424 ctx = Context(TLSv1_METHOD)
425 self.assertRaises(TypeError, ctx.use_certificate)
426 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
427 self.assertRaises(TypeError, ctx.use_certificate, X509(), "hello, world")
428
429
430 def test_use_certificate_uninitialized(self):
431 """
432 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
433 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
434 initialized (ie, which does not actually have any certificate data).
435 """
436 ctx = Context(TLSv1_METHOD)
437 self.assertRaises(Error, ctx.use_certificate, X509())
438
439
440 def test_use_certificate(self):
441 """
442 :py:obj:`Context.use_certificate` sets the certificate which will be
443 used to identify connections created using the context.
444 """
445 # TODO
446 # Hard to assert anything. But we could set a privatekey then ask
447 # OpenSSL if the cert and key agree using check_privatekey. Then as
448 # long as check_privatekey works right we're good...
449 ctx = Context(TLSv1_METHOD)
450 ctx.use_certificate(load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
451
452
453 def test_use_certificate_file_wrong_args(self):
454 """
455 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
456 called with zero arguments or more than two arguments, or if the first
457 argument is not a byte string or the second argumnent is not an integer.
458 """
459 ctx = Context(TLSv1_METHOD)
460 self.assertRaises(TypeError, ctx.use_certificate_file)
461 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile", object())
462 self.assertRaises(
463 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM, object())
464 self.assertRaises(
465 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
466 self.assertRaises(
467 TypeError, ctx.use_certificate_file, b"somefile", object())
468
469
470 def test_use_certificate_file_missing(self):
471 """
472 :py:obj:`Context.use_certificate_file` raises
473 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does not
474 exist.
475 """
476 ctx = Context(TLSv1_METHOD)
477 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
478
479
480 def test_use_certificate_file(self):
481 """
482 :py:obj:`Context.use_certificate` sets the certificate which will be
483 used to identify connections created using the context.
484 """
485 # TODO
486 # Hard to assert anything. But we could set a privatekey then ask
487 # OpenSSL if the cert and key agree using check_privatekey. Then as
488 # long as check_privatekey works right we're good...
489 pem_filename = self.mktemp()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500490 with open(pem_filename, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800491 pem_file.write(cleartextCertificatePEM)
492
493 ctx = Context(TLSv1_METHOD)
494 ctx.use_certificate_file(pem_filename)
495
496
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500497 if not PY3:
498 def test_use_certificate_file_long(self):
499 """
500 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
501 filetype of type :py:obj:`long` as well as :py:obj:`int`.
502 """
503 pem_filename = self.mktemp()
504 with open(pem_filename, "wb") as pem_file:
505 pem_file.write(cleartextCertificatePEM)
506
507 ctx = Context(TLSv1_METHOD)
508 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
509
510
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500511 def test_check_privatekey_valid(self):
512 """
513 :py:obj:`Context.check_privatekey` returns :py:obj:`None` if the
514 :py:obj:`Context` instance has been configured to use a matched key and
515 certificate pair.
516 """
517 key = load_privatekey(FILETYPE_PEM, client_key_pem)
518 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
519 context = Context(TLSv1_METHOD)
520 context.use_privatekey(key)
521 context.use_certificate(cert)
522 self.assertIs(None, context.check_privatekey())
523
524
525 def test_check_privatekey_invalid(self):
526 """
527 :py:obj:`Context.check_privatekey` raises :py:obj:`Error` if the
528 :py:obj:`Context` instance has been configured to use a key and
529 certificate pair which don't relate to each other.
530 """
531 key = load_privatekey(FILETYPE_PEM, client_key_pem)
532 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
533 context = Context(TLSv1_METHOD)
534 context.use_privatekey(key)
535 context.use_certificate(cert)
536 self.assertRaises(Error, context.check_privatekey)
537
538
539 def test_check_privatekey_wrong_args(self):
540 """
541 :py:obj:`Context.check_privatekey` raises :py:obj:`TypeError` if called
542 with other than no arguments.
543 """
544 context = Context(TLSv1_METHOD)
545 self.assertRaises(TypeError, context.check_privatekey, object())
546
547
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400548 def test_set_app_data_wrong_args(self):
549 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900550 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called with other than
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400551 one argument.
552 """
553 context = Context(TLSv1_METHOD)
554 self.assertRaises(TypeError, context.set_app_data)
555 self.assertRaises(TypeError, context.set_app_data, None, None)
556
557
558 def test_get_app_data_wrong_args(self):
559 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900560 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400561 arguments.
562 """
563 context = Context(TLSv1_METHOD)
564 self.assertRaises(TypeError, context.get_app_data, None)
565
566
567 def test_app_data(self):
568 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900569 :py:obj:`Context.set_app_data` stores an object for later retrieval using
570 :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400571 """
572 app_data = object()
573 context = Context(TLSv1_METHOD)
574 context.set_app_data(app_data)
575 self.assertIdentical(context.get_app_data(), app_data)
576
577
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400578 def test_set_options_wrong_args(self):
579 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900580 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with the wrong
581 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400582 """
583 context = Context(TLSv1_METHOD)
584 self.assertRaises(TypeError, context.set_options)
585 self.assertRaises(TypeError, context.set_options, None)
586 self.assertRaises(TypeError, context.set_options, 1, None)
587
588
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500589 def test_set_options(self):
590 """
591 :py:obj:`Context.set_options` returns the new options value.
592 """
593 context = Context(TLSv1_METHOD)
594 options = context.set_options(OP_NO_SSLv2)
595 self.assertTrue(OP_NO_SSLv2 & options)
596
597
598 if not PY3:
599 def test_set_options_long(self):
600 """
601 On Python 2 :py:obj:`Context.set_options` accepts values of type
602 :py:obj:`long` as well as :py:obj:`int`.
603 """
604 context = Context(TLSv1_METHOD)
605 options = context.set_options(long(OP_NO_SSLv2))
606 self.assertTrue(OP_NO_SSLv2 & options)
607
608
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300609 def test_set_mode_wrong_args(self):
610 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400611 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with the wrong
612 number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300613 """
614 context = Context(TLSv1_METHOD)
615 self.assertRaises(TypeError, context.set_mode)
616 self.assertRaises(TypeError, context.set_mode, None)
617 self.assertRaises(TypeError, context.set_mode, 1, None)
618
619
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400620 if MODE_RELEASE_BUFFERS is not None:
621 def test_set_mode(self):
622 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400623 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the newly
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400624 set mode.
625 """
626 context = Context(TLSv1_METHOD)
627 self.assertTrue(
628 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500629
630 if not PY3:
631 def test_set_mode_long(self):
632 """
633 On Python 2 :py:obj:`Context.set_mode` accepts values of type
634 :py:obj:`long` as well as :py:obj:`int`.
635 """
636 context = Context(TLSv1_METHOD)
637 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
638 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400639 else:
640 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
641
642
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400643 def test_set_timeout_wrong_args(self):
644 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900645 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with the wrong
646 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400647 """
648 context = Context(TLSv1_METHOD)
649 self.assertRaises(TypeError, context.set_timeout)
650 self.assertRaises(TypeError, context.set_timeout, None)
651 self.assertRaises(TypeError, context.set_timeout, 1, None)
652
653
654 def test_get_timeout_wrong_args(self):
655 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900656 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400657 """
658 context = Context(TLSv1_METHOD)
659 self.assertRaises(TypeError, context.get_timeout, None)
660
661
662 def test_timeout(self):
663 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900664 :py:obj:`Context.set_timeout` sets the session timeout for all connections
665 created using the context object. :py:obj:`Context.get_timeout` retrieves this
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400666 value.
667 """
668 context = Context(TLSv1_METHOD)
669 context.set_timeout(1234)
670 self.assertEquals(context.get_timeout(), 1234)
671
672
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500673 if not PY3:
674 def test_timeout_long(self):
675 """
676 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
677 `long` as well as int.
678 """
679 context = Context(TLSv1_METHOD)
680 context.set_timeout(long(1234))
681 self.assertEquals(context.get_timeout(), 1234)
682
683
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400684 def test_set_verify_depth_wrong_args(self):
685 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900686 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called with the wrong
687 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400688 """
689 context = Context(TLSv1_METHOD)
690 self.assertRaises(TypeError, context.set_verify_depth)
691 self.assertRaises(TypeError, context.set_verify_depth, None)
692 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
693
694
695 def test_get_verify_depth_wrong_args(self):
696 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900697 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400698 """
699 context = Context(TLSv1_METHOD)
700 self.assertRaises(TypeError, context.get_verify_depth, None)
701
702
703 def test_verify_depth(self):
704 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900705 :py:obj:`Context.set_verify_depth` sets the number of certificates in a chain
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400706 to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900707 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400708 """
709 context = Context(TLSv1_METHOD)
710 context.set_verify_depth(11)
711 self.assertEquals(context.get_verify_depth(), 11)
712
713
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500714 if not PY3:
715 def test_verify_depth_long(self):
716 """
717 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
718 type `long` as well as int.
719 """
720 context = Context(TLSv1_METHOD)
721 context.set_verify_depth(long(11))
722 self.assertEquals(context.get_verify_depth(), 11)
723
724
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400725 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400726 """
727 Write a new private key out to a new file, encrypted using the given
728 passphrase. Return the path to the new file.
729 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400730 key = PKey()
731 key.generate_key(TYPE_RSA, 128)
732 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400733 fObj = open(pemFile, 'w')
734 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
735 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400736 fObj.close()
737 return pemFile
738
739
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400740 def test_set_passwd_cb_wrong_args(self):
741 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900742 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called with the
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400743 wrong arguments or with a non-callable first argument.
744 """
745 context = Context(TLSv1_METHOD)
746 self.assertRaises(TypeError, context.set_passwd_cb)
747 self.assertRaises(TypeError, context.set_passwd_cb, None)
748 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
749
750
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400751 def test_set_passwd_cb(self):
752 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900753 :py:obj:`Context.set_passwd_cb` accepts a callable which will be invoked when
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400754 a private key is loaded from an encrypted PEM.
755 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400756 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400757 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400758 calledWith = []
759 def passphraseCallback(maxlen, verify, extra):
760 calledWith.append((maxlen, verify, extra))
761 return passphrase
762 context = Context(TLSv1_METHOD)
763 context.set_passwd_cb(passphraseCallback)
764 context.use_privatekey_file(pemFile)
765 self.assertTrue(len(calledWith), 1)
766 self.assertTrue(isinstance(calledWith[0][0], int))
767 self.assertTrue(isinstance(calledWith[0][1], int))
768 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400769
770
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400771 def test_passwd_callback_exception(self):
772 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900773 :py:obj:`Context.use_privatekey_file` propagates any exception raised by the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400774 passphrase callback.
775 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400776 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400777 def passphraseCallback(maxlen, verify, extra):
778 raise RuntimeError("Sorry, I am a fail.")
779
780 context = Context(TLSv1_METHOD)
781 context.set_passwd_cb(passphraseCallback)
782 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
783
784
785 def test_passwd_callback_false(self):
786 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900787 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400788 passphrase callback returns a false value.
789 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400790 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400791 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500792 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400793
794 context = Context(TLSv1_METHOD)
795 context.set_passwd_cb(passphraseCallback)
796 self.assertRaises(Error, context.use_privatekey_file, pemFile)
797
798
799 def test_passwd_callback_non_string(self):
800 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900801 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400802 passphrase callback returns a true non-string value.
803 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400804 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400805 def passphraseCallback(maxlen, verify, extra):
806 return 10
807
808 context = Context(TLSv1_METHOD)
809 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800810 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400811
812
813 def test_passwd_callback_too_long(self):
814 """
815 If the passphrase returned by the passphrase callback returns a string
816 longer than the indicated maximum length, it is truncated.
817 """
818 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400819 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400820 pemFile = self._write_encrypted_pem(passphrase)
821 def passphraseCallback(maxlen, verify, extra):
822 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400823 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400824
825 context = Context(TLSv1_METHOD)
826 context.set_passwd_cb(passphraseCallback)
827 # This shall succeed because the truncated result is the correct
828 # passphrase.
829 context.use_privatekey_file(pemFile)
830
831
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400832 def test_set_info_callback(self):
833 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900834 :py:obj:`Context.set_info_callback` accepts a callable which will be invoked
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400835 when certain information about an SSL connection is available.
836 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500837 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400838
839 clientSSL = Connection(Context(TLSv1_METHOD), client)
840 clientSSL.set_connect_state()
841
842 called = []
843 def info(conn, where, ret):
844 called.append((conn, where, ret))
845 context = Context(TLSv1_METHOD)
846 context.set_info_callback(info)
847 context.use_certificate(
848 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
849 context.use_privatekey(
850 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
851
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400852 serverSSL = Connection(context, server)
853 serverSSL.set_accept_state()
854
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500855 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400856
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500857 # The callback must always be called with a Connection instance as the
858 # first argument. It would probably be better to split this into
859 # separate tests for client and server side info callbacks so we could
860 # assert it is called with the right Connection instance. It would
861 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500862 notConnections = [
863 conn for (conn, where, ret) in called
864 if not isinstance(conn, Connection)]
865 self.assertEqual(
866 [], notConnections,
867 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400868
869
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400870 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400871 """
872 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400873 its :py:obj:`load_verify_locations` method with the given arguments.
874 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400875 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500876 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400877
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400878 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400879 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400880 # Require that the server certificate verify properly or the
881 # connection will fail.
882 clientContext.set_verify(
883 VERIFY_PEER,
884 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
885
886 clientSSL = Connection(clientContext, client)
887 clientSSL.set_connect_state()
888
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400889 serverContext = Context(TLSv1_METHOD)
890 serverContext.use_certificate(
891 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
892 serverContext.use_privatekey(
893 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
894
895 serverSSL = Connection(serverContext, server)
896 serverSSL.set_accept_state()
897
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400898 # Without load_verify_locations above, the handshake
899 # will fail:
900 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
901 # 'certificate verify failed')]
902 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400903
904 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400905 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400906
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500907
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400908 def test_load_verify_file(self):
909 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900910 :py:obj:`Context.load_verify_locations` accepts a file name and uses the
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400911 certificates within for verification purposes.
912 """
913 cafile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400914 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400915 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400916 fObj.close()
917
918 self._load_verify_locations_test(cafile)
919
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400920
Abraham Martinef063482015-03-25 14:06:24 +0000921 def test_load_verify_warning(self):
922 """
923 :py:obj:`Context.load_verify_locations` accepts a file name and uses the
924 certificates within for verification purposes. Raises a warning when
925 using a text in cafile.
926 """
927 cafile = self.mktemp()
928 fObj = open(cafile, 'w')
929 fObj.write(cleartextCertificatePEM.decode('ascii'))
930 fObj.close()
931
932 with catch_warnings(record=True) as w:
933 simplefilter("always")
934 if version_info.major == 2:
935 self._load_verify_locations_test(unicode(cafile))
936 self.assertTrue("unicode in cafile is no longer accepted, use bytes" in str(w[-1].message))
937 elif version_info.major == 3:
938 self._load_verify_locations_test(cafile.decode())
939 self.assertTrue("str in cafile is no longer accepted, use bytes" in str(w[-1].message))
940 self.assertTrue(issubclass(w[-1].category, DeprecationWarning))
941
942
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400943 def test_load_verify_invalid_file(self):
944 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900945 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when passed a
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400946 non-existent cafile.
947 """
948 clientContext = Context(TLSv1_METHOD)
949 self.assertRaises(
950 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400951
952
953 def test_load_verify_directory(self):
954 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900955 :py:obj:`Context.load_verify_locations` accepts a directory name and uses
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400956 the certificates within for verification purposes.
957 """
958 capath = self.mktemp()
959 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400960 # Hash values computed manually with c_rehash to avoid depending on
961 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
962 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500963 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400964 cafile = join(capath, name)
965 fObj = open(cafile, 'w')
966 fObj.write(cleartextCertificatePEM.decode('ascii'))
967 fObj.close()
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400968
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400969 self._load_verify_locations_test(None, capath)
970
971
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400972 def test_load_verify_locations_wrong_args(self):
973 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900974 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if called with
975 the wrong number of arguments or with non-:py:obj:`str` arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400976 """
977 context = Context(TLSv1_METHOD)
978 self.assertRaises(TypeError, context.load_verify_locations)
979 self.assertRaises(TypeError, context.load_verify_locations, object())
980 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
981 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
982
983
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400984 if platform == "win32":
985 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400986 "See LP#404343 and LP#404344."
987 else:
988 def test_set_default_verify_paths(self):
989 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900990 :py:obj:`Context.set_default_verify_paths` causes the platform-specific CA
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400991 certificate locations to be used for verification purposes.
992 """
993 # Testing this requires a server with a certificate signed by one of
994 # the CAs in the platform CA location. Getting one of those costs
995 # money. Fortunately (or unfortunately, depending on your
996 # perspective), it's easy to think of a public server on the
997 # internet which has such a certificate. Connecting to the network
998 # in a unit test is bad, but it's the only way I can think of to
999 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001000
Alex Gaynorb586da32014-11-15 09:22:21 -08001001 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
1002 context = Context(TLSv1_METHOD)
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001003 context.set_default_verify_paths()
1004 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02001005 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001006 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001007
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001008 client = socket()
1009 client.connect(('verisign.com', 443))
1010 clientSSL = Connection(context, client)
1011 clientSSL.set_connect_state()
1012 clientSSL.do_handshake()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001013 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001014 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001015
1016
1017 def test_set_default_verify_paths_signature(self):
1018 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001019 :py:obj:`Context.set_default_verify_paths` takes no arguments and raises
1020 :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001021 """
1022 context = Context(TLSv1_METHOD)
1023 self.assertRaises(TypeError, context.set_default_verify_paths, None)
1024 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
1025 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001026
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001027
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001028 def test_add_extra_chain_cert_invalid_cert(self):
1029 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001030 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if called with
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001031 other than one argument or if called with an object which is not an
Jonathan Ballet648875f2011-07-16 14:14:58 +09001032 instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001033 """
1034 context = Context(TLSv1_METHOD)
1035 self.assertRaises(TypeError, context.add_extra_chain_cert)
1036 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
1037 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
1038
1039
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001040 def _handshake_test(self, serverContext, clientContext):
1041 """
1042 Verify that a client and server created with the given contexts can
1043 successfully handshake and communicate.
1044 """
1045 serverSocket, clientSocket = socket_pair()
1046
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001047 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001048 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001049
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001050 client = Connection(clientContext, clientSocket)
1051 client.set_connect_state()
1052
1053 # Make them talk to each other.
1054 # self._interactInMemory(client, server)
1055 for i in range(3):
1056 for s in [client, server]:
1057 try:
1058 s.do_handshake()
1059 except WantReadError:
1060 pass
1061
1062
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001063 def test_set_verify_callback_connection_argument(self):
1064 """
1065 The first argument passed to the verify callback is the
1066 :py:class:`Connection` instance for which verification is taking place.
1067 """
1068 serverContext = Context(TLSv1_METHOD)
1069 serverContext.use_privatekey(
1070 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1071 serverContext.use_certificate(
1072 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1073 serverConnection = Connection(serverContext, None)
1074
1075 class VerifyCallback(object):
1076 def callback(self, connection, *args):
1077 self.connection = connection
1078 return 1
1079
1080 verify = VerifyCallback()
1081 clientContext = Context(TLSv1_METHOD)
1082 clientContext.set_verify(VERIFY_PEER, verify.callback)
1083 clientConnection = Connection(clientContext, None)
1084 clientConnection.set_connect_state()
1085
1086 self._handshakeInMemory(clientConnection, serverConnection)
1087
1088 self.assertIdentical(verify.connection, clientConnection)
1089
1090
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001091 def test_set_verify_callback_exception(self):
1092 """
1093 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1094 exception, verification fails and the exception is propagated to the
1095 caller of :py:obj:`Connection.do_handshake`.
1096 """
1097 serverContext = Context(TLSv1_METHOD)
1098 serverContext.use_privatekey(
1099 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1100 serverContext.use_certificate(
1101 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1102
1103 clientContext = Context(TLSv1_METHOD)
1104 def verify_callback(*args):
1105 raise Exception("silly verify failure")
1106 clientContext.set_verify(VERIFY_PEER, verify_callback)
1107
1108 exc = self.assertRaises(
1109 Exception, self._handshake_test, serverContext, clientContext)
1110 self.assertEqual("silly verify failure", str(exc))
1111
1112
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001113 def test_add_extra_chain_cert(self):
1114 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001115 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509` instance to add to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001116 the certificate chain.
1117
Jonathan Ballet648875f2011-07-16 14:14:58 +09001118 See :py:obj:`_create_certificate_chain` for the details of the certificate
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001119 chain tested.
1120
1121 The chain is tested by starting a server with scert and connecting
1122 to it with a client which trusts cacert and requires verification to
1123 succeed.
1124 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001125 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001126 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1127
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001128 # Dump the CA certificate to a file because that's the only way to load
1129 # it as a trusted CA in the client context.
1130 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001131 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001132 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001133 fObj.close()
1134
1135 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001136 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001137 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001138 fObj.close()
1139
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001140 # Create the server context
1141 serverContext = Context(TLSv1_METHOD)
1142 serverContext.use_privatekey(skey)
1143 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001144 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001145 serverContext.add_extra_chain_cert(icert)
1146
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001147 # Create the client
1148 clientContext = Context(TLSv1_METHOD)
1149 clientContext.set_verify(
1150 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001151 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001152
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001153 # Try it out.
1154 self._handshake_test(serverContext, clientContext)
1155
1156
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001157 def test_use_certificate_chain_file(self):
1158 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001159 :py:obj:`Context.use_certificate_chain_file` reads a certificate chain from
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001160 the specified file.
1161
1162 The chain is tested by starting a server with scert and connecting
1163 to it with a client which trusts cacert and requires verification to
1164 succeed.
1165 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001166 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001167 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1168
1169 # Write out the chain file.
1170 chainFile = self.mktemp()
Jean-Paul Calderoned8607982014-01-18 10:30:55 -05001171 fObj = open(chainFile, 'wb')
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001172 # Most specific to least general.
Jean-Paul Calderoned8607982014-01-18 10:30:55 -05001173 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1174 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1175 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001176 fObj.close()
1177
1178 serverContext = Context(TLSv1_METHOD)
1179 serverContext.use_certificate_chain_file(chainFile)
1180 serverContext.use_privatekey(skey)
1181
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001182 fObj = open('ca.pem', 'w')
1183 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001184 fObj.close()
1185
1186 clientContext = Context(TLSv1_METHOD)
1187 clientContext.set_verify(
1188 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001189 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001190
1191 self._handshake_test(serverContext, clientContext)
1192
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001193
1194 def test_use_certificate_chain_file_wrong_args(self):
1195 """
1196 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1197 if passed zero or more than one argument or when passed a non-byte
1198 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error` when
1199 passed a bad chain file name (for example, the name of a file which does
1200 not exist).
1201 """
1202 context = Context(TLSv1_METHOD)
1203 self.assertRaises(TypeError, context.use_certificate_chain_file)
1204 self.assertRaises(TypeError, context.use_certificate_chain_file, object())
1205 self.assertRaises(TypeError, context.use_certificate_chain_file, b"foo", object())
1206
1207 self.assertRaises(Error, context.use_certificate_chain_file, self.mktemp())
1208
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001209 # XXX load_client_ca
1210 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001211
1212 def test_get_verify_mode_wrong_args(self):
1213 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001214 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001215 arguments.
1216 """
1217 context = Context(TLSv1_METHOD)
1218 self.assertRaises(TypeError, context.get_verify_mode, None)
1219
1220
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001221 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001222 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001223 :py:obj:`Context.get_verify_mode` returns the verify mode flags previously
1224 passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001225 """
1226 context = Context(TLSv1_METHOD)
1227 self.assertEquals(context.get_verify_mode(), 0)
1228 context.set_verify(
1229 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1230 self.assertEquals(
1231 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1232
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001233
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001234 if not PY3:
1235 def test_set_verify_mode_long(self):
1236 """
1237 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1238 type :py:obj:`long` as well as :py:obj:`int`.
1239 """
1240 context = Context(TLSv1_METHOD)
1241 self.assertEquals(context.get_verify_mode(), 0)
1242 context.set_verify(
1243 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None)
1244 self.assertEquals(
1245 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1246
1247
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001248 def test_load_tmp_dh_wrong_args(self):
1249 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001250 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
1251 number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001252 """
1253 context = Context(TLSv1_METHOD)
1254 self.assertRaises(TypeError, context.load_tmp_dh)
1255 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1256 self.assertRaises(TypeError, context.load_tmp_dh, object())
1257
1258
1259 def test_load_tmp_dh_missing_file(self):
1260 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001261 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the specified file
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001262 does not exist.
1263 """
1264 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001265 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001266
1267
1268 def test_load_tmp_dh(self):
1269 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001270 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001271 specified file.
1272 """
1273 context = Context(TLSv1_METHOD)
1274 dhfilename = self.mktemp()
1275 dhfile = open(dhfilename, "w")
1276 dhfile.write(dhparam)
1277 dhfile.close()
1278 context.load_tmp_dh(dhfilename)
1279 # XXX What should I assert here? -exarkun
1280
1281
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001282 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001283 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001284 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001285 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001286 """
1287 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001288 for curve in get_elliptic_curves():
1289 # The only easily "assertable" thing is that it does not raise an
1290 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001291 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001292
1293
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001294 def test_set_cipher_list_bytes(self):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001295 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001296 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
1297 ciphers which connections created with the context object will be able
1298 to choose from.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001299 """
1300 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001301 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001302 conn = Connection(context, None)
1303 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001304
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001305
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001306 def test_set_cipher_list_text(self):
1307 """
1308 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
1309 the ciphers which connections created with the context object will be
1310 able to choose from.
1311 """
1312 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -05001313 context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001314 conn = Connection(context, None)
1315 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
1316
1317
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001318 def test_set_cipher_list_wrong_args(self):
1319 """
Jean-Paul Calderone17044832014-01-18 10:20:11 -05001320 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
1321 passed zero arguments or more than one argument or when passed a
1322 non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001323 passed an incorrect cipher list string.
1324 """
1325 context = Context(TLSv1_METHOD)
1326 self.assertRaises(TypeError, context.set_cipher_list)
1327 self.assertRaises(TypeError, context.set_cipher_list, object())
1328 self.assertRaises(TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object())
1329
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001330 self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001331
1332
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001333 def test_set_session_cache_mode_wrong_args(self):
1334 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001335 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1336 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001337 """
1338 context = Context(TLSv1_METHOD)
1339 self.assertRaises(TypeError, context.set_session_cache_mode)
1340 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1341
1342
1343 def test_get_session_cache_mode_wrong_args(self):
1344 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001345 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1346 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001347 """
1348 context = Context(TLSv1_METHOD)
1349 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1350
1351
1352 def test_session_cache_mode(self):
1353 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001354 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1355 cached. The setting can be retrieved via
1356 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001357 """
1358 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001359 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001360 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1361 self.assertEqual(SESS_CACHE_OFF, off)
1362 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1363
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001364 if not PY3:
1365 def test_session_cache_mode_long(self):
1366 """
1367 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1368 of type :py:obj:`long` as well as :py:obj:`int`.
1369 """
1370 context = Context(TLSv1_METHOD)
1371 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1372 self.assertEqual(
1373 SESS_CACHE_BOTH, context.get_session_cache_mode())
1374
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001375
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001376 def test_get_cert_store(self):
1377 """
1378 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store` instance.
1379 """
1380 context = Context(TLSv1_METHOD)
1381 store = context.get_cert_store()
1382 self.assertIsInstance(store, X509Store)
1383
1384
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001385
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001386class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1387 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001388 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
1389 :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001390 """
1391 def test_wrong_args(self):
1392 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001393 :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001394 with other than one argument.
1395 """
1396 context = Context(TLSv1_METHOD)
1397 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1398 self.assertRaises(
1399 TypeError, context.set_tlsext_servername_callback, 1, 2)
1400
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001401
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001402 def test_old_callback_forgotten(self):
1403 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001404 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001405 callback, the one it replaces is dereferenced.
1406 """
1407 def callback(connection):
1408 pass
1409
1410 def replacement(connection):
1411 pass
1412
1413 context = Context(TLSv1_METHOD)
1414 context.set_tlsext_servername_callback(callback)
1415
1416 tracker = ref(callback)
1417 del callback
1418
1419 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001420
1421 # One run of the garbage collector happens to work on CPython. PyPy
1422 # doesn't collect the underlying object until a second run for whatever
1423 # reason. That's fine, it still demonstrates our code has properly
1424 # dropped the reference.
1425 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001426 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001427
1428 callback = tracker()
1429 if callback is not None:
1430 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001431 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001432 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001433
1434
1435 def test_no_servername(self):
1436 """
1437 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001438 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
1439 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001440 """
1441 args = []
1442 def servername(conn):
1443 args.append((conn, conn.get_servername()))
1444 context = Context(TLSv1_METHOD)
1445 context.set_tlsext_servername_callback(servername)
1446
1447 # Lose our reference to it. The Context is responsible for keeping it
1448 # alive now.
1449 del servername
1450 collect()
1451
1452 # Necessary to actually accept the connection
1453 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1454 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1455
1456 # Do a little connection to trigger the logic
1457 server = Connection(context, None)
1458 server.set_accept_state()
1459
1460 client = Connection(Context(TLSv1_METHOD), None)
1461 client.set_connect_state()
1462
1463 self._interactInMemory(server, client)
1464
1465 self.assertEqual([(server, None)], args)
1466
1467
1468 def test_servername(self):
1469 """
1470 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +09001471 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
1472 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001473 """
1474 args = []
1475 def servername(conn):
1476 args.append((conn, conn.get_servername()))
1477 context = Context(TLSv1_METHOD)
1478 context.set_tlsext_servername_callback(servername)
1479
1480 # Necessary to actually accept the connection
1481 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1482 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1483
1484 # Do a little connection to trigger the logic
1485 server = Connection(context, None)
1486 server.set_accept_state()
1487
1488 client = Connection(Context(TLSv1_METHOD), None)
1489 client.set_connect_state()
1490 client.set_tlsext_host_name(b("foo1.example.com"))
1491
1492 self._interactInMemory(server, client)
1493
1494 self.assertEqual([(server, b("foo1.example.com"))], args)
1495
1496
1497
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001498class SessionTests(TestCase):
1499 """
1500 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1501 """
1502 def test_construction(self):
1503 """
1504 :py:class:`Session` can be constructed with no arguments, creating a new
1505 instance of that type.
1506 """
1507 new_session = Session()
1508 self.assertTrue(isinstance(new_session, Session))
1509
1510
1511 def test_construction_wrong_args(self):
1512 """
1513 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
1514 is raised.
1515 """
1516 self.assertRaises(TypeError, Session, 123)
1517 self.assertRaises(TypeError, Session, "hello")
1518 self.assertRaises(TypeError, Session, object())
1519
1520
1521
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001522class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05001523 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001524 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001525 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001526 # XXX get_peer_certificate -> None
1527 # XXX sock_shutdown
1528 # XXX master_key -> TypeError
1529 # XXX server_random -> TypeError
1530 # XXX state_string
1531 # XXX connect -> TypeError
1532 # XXX connect_ex -> TypeError
1533 # XXX set_connect_state -> TypeError
1534 # XXX set_accept_state -> TypeError
1535 # XXX renegotiate_pending
1536 # XXX do_handshake -> TypeError
1537 # XXX bio_read -> TypeError
1538 # XXX recv -> TypeError
1539 # XXX send -> TypeError
1540 # XXX bio_write -> TypeError
1541
Rick Deane15b1472009-07-09 15:53:42 -05001542 def test_type(self):
1543 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001544 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001545 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05001546 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001547 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05001548 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001549 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05001550
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001551
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001552 def test_get_context(self):
1553 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001554 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
1555 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001556 """
1557 context = Context(TLSv1_METHOD)
1558 connection = Connection(context, None)
1559 self.assertIdentical(connection.get_context(), context)
1560
1561
1562 def test_get_context_wrong_args(self):
1563 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001564 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001565 arguments.
1566 """
1567 connection = Connection(Context(TLSv1_METHOD), None)
1568 self.assertRaises(TypeError, connection.get_context, None)
1569
1570
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001571 def test_set_context_wrong_args(self):
1572 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001573 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
1574 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001575 than 1.
1576 """
1577 ctx = Context(TLSv1_METHOD)
1578 connection = Connection(ctx, None)
1579 self.assertRaises(TypeError, connection.set_context)
1580 self.assertRaises(TypeError, connection.set_context, object())
1581 self.assertRaises(TypeError, connection.set_context, "hello")
1582 self.assertRaises(TypeError, connection.set_context, 1)
1583 self.assertRaises(TypeError, connection.set_context, 1, 2)
1584 self.assertRaises(
1585 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
1586 self.assertIdentical(ctx, connection.get_context())
1587
1588
1589 def test_set_context(self):
1590 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001591 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001592 for the connection.
1593 """
1594 original = Context(SSLv23_METHOD)
1595 replacement = Context(TLSv1_METHOD)
1596 connection = Connection(original, None)
1597 connection.set_context(replacement)
1598 self.assertIdentical(replacement, connection.get_context())
1599 # Lose our references to the contexts, just in case the Connection isn't
1600 # properly managing its own contributions to their reference counts.
1601 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001602 collect()
1603
1604
1605 def test_set_tlsext_host_name_wrong_args(self):
1606 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001607 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001608 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09001609 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001610 """
1611 conn = Connection(Context(TLSv1_METHOD), None)
1612 self.assertRaises(TypeError, conn.set_tlsext_host_name)
1613 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
1614 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
1615 self.assertRaises(
1616 TypeError, conn.set_tlsext_host_name, b("with\0null"))
1617
1618 if version_info >= (3,):
1619 # On Python 3.x, don't accidentally implicitly convert from text.
1620 self.assertRaises(
1621 TypeError,
1622 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001623
1624
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001625 def test_get_servername_wrong_args(self):
1626 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001627 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001628 arguments.
1629 """
1630 connection = Connection(Context(TLSv1_METHOD), None)
1631 self.assertRaises(TypeError, connection.get_servername, object())
1632 self.assertRaises(TypeError, connection.get_servername, 1)
1633 self.assertRaises(TypeError, connection.get_servername, "hello")
1634
1635
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001636 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001637 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001638 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001639 immediate read.
1640 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001641 connection = Connection(Context(TLSv1_METHOD), None)
1642 self.assertEquals(connection.pending(), 0)
1643
1644
1645 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001646 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001647 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001648 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001649 connection = Connection(Context(TLSv1_METHOD), None)
1650 self.assertRaises(TypeError, connection.pending, None)
1651
1652
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001653 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001654 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001655 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001656 argument or with the wrong number of arguments.
1657 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001658 connection = Connection(Context(TLSv1_METHOD), socket())
1659 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001660 self.assertRaises(TypeError, connection.connect)
1661 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001662
1663
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001664 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001665 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001666 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001667 connect method raises it.
1668 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001669 client = socket()
1670 context = Context(TLSv1_METHOD)
1671 clientSSL = Connection(context, client)
1672 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04001673 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001674
1675
1676 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001677 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001678 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001679 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001680 port = socket()
1681 port.bind(('', 0))
1682 port.listen(3)
1683
1684 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001685 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
1686 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001687
1688
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001689 if platform == "darwin":
1690 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
1691 else:
1692 def test_connect_ex(self):
1693 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001694 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001695 errno instead of raising an exception.
1696 """
1697 port = socket()
1698 port.bind(('', 0))
1699 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001700
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001701 clientSSL = Connection(Context(TLSv1_METHOD), socket())
1702 clientSSL.setblocking(False)
1703 result = clientSSL.connect_ex(port.getsockname())
1704 expected = (EINPROGRESS, EWOULDBLOCK)
1705 self.assertTrue(
1706 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001707
1708
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001709 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001710 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001711 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001712 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001713 connection = Connection(Context(TLSv1_METHOD), socket())
1714 self.assertRaises(TypeError, connection.accept, None)
1715
1716
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001717 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001718 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001719 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
1720 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001721 connection originated from.
1722 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001723 ctx = Context(TLSv1_METHOD)
1724 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1725 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001726 port = socket()
1727 portSSL = Connection(ctx, port)
1728 portSSL.bind(('', 0))
1729 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001730
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001731 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001732
1733 # Calling portSSL.getsockname() here to get the server IP address sounds
1734 # great, but frequently fails on Windows.
1735 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001736
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001737 serverSSL, address = portSSL.accept()
1738
1739 self.assertTrue(isinstance(serverSSL, Connection))
1740 self.assertIdentical(serverSSL.get_context(), ctx)
1741 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001742
1743
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001744 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001745 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001746 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001747 number of arguments or with arguments other than integers.
1748 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001749 connection = Connection(Context(TLSv1_METHOD), None)
1750 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04001751 self.assertRaises(TypeError, connection.get_shutdown, None)
1752 self.assertRaises(TypeError, connection.set_shutdown)
1753 self.assertRaises(TypeError, connection.set_shutdown, None)
1754 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001755
1756
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001757 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001758 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001759 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001760 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001761 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001762 self.assertFalse(server.shutdown())
1763 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001764 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001765 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
1766 client.shutdown()
1767 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
1768 self.assertRaises(ZeroReturnError, server.recv, 1024)
1769 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001770
1771
Paul Aurichc85e0862015-01-08 08:34:33 -08001772 def test_shutdown_closed(self):
1773 """
1774 If the underlying socket is closed, :py:obj:`Connection.shutdown` propagates the
1775 write error from the low level write call.
1776 """
1777 server, client = self._loopback()
1778 server.sock_shutdown(2)
1779 exc = self.assertRaises(SysCallError, server.shutdown)
1780 if platform == "win32":
1781 self.assertEqual(exc.args[0], ESHUTDOWN)
1782 else:
1783 self.assertEqual(exc.args[0], EPIPE)
1784
1785
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001786 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001787 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001788 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001789 process.
1790 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001791 connection = Connection(Context(TLSv1_METHOD), socket())
1792 connection.set_shutdown(RECEIVED_SHUTDOWN)
1793 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1794
1795
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05001796 if not PY3:
1797 def test_set_shutdown_long(self):
1798 """
1799 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
1800 of type :py:obj:`long` as well as :py:obj:`int`.
1801 """
1802 connection = Connection(Context(TLSv1_METHOD), socket())
1803 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
1804 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1805
1806
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001807 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001808 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001809 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
1810 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001811 with any arguments.
1812 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001813 conn = Connection(Context(TLSv1_METHOD), None)
1814 self.assertRaises(TypeError, conn.get_app_data, None)
1815 self.assertRaises(TypeError, conn.set_app_data)
1816 self.assertRaises(TypeError, conn.set_app_data, None, None)
1817
1818
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001819 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001820 """
1821 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001822 :py:obj:`Connection.set_app_data` and later retrieved with
1823 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001824 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001825 conn = Connection(Context(TLSv1_METHOD), None)
1826 app_data = object()
1827 conn.set_app_data(app_data)
1828 self.assertIdentical(conn.get_app_data(), app_data)
1829
1830
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001831 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001832 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001833 :py:obj:`Connection.makefile` is not implemented and calling that method raises
1834 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001835 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001836 conn = Connection(Context(TLSv1_METHOD), None)
1837 self.assertRaises(NotImplementedError, conn.makefile)
1838
1839
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001840 def test_get_peer_cert_chain_wrong_args(self):
1841 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001842 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001843 arguments.
1844 """
1845 conn = Connection(Context(TLSv1_METHOD), None)
1846 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
1847 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
1848 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
1849 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
1850
1851
1852 def test_get_peer_cert_chain(self):
1853 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001854 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001855 the connected server returned for the certification verification.
1856 """
1857 chain = _create_certificate_chain()
1858 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1859
1860 serverContext = Context(TLSv1_METHOD)
1861 serverContext.use_privatekey(skey)
1862 serverContext.use_certificate(scert)
1863 serverContext.add_extra_chain_cert(icert)
1864 serverContext.add_extra_chain_cert(cacert)
1865 server = Connection(serverContext, None)
1866 server.set_accept_state()
1867
1868 # Create the client
1869 clientContext = Context(TLSv1_METHOD)
1870 clientContext.set_verify(VERIFY_NONE, verify_cb)
1871 client = Connection(clientContext, None)
1872 client.set_connect_state()
1873
1874 self._interactInMemory(client, server)
1875
1876 chain = client.get_peer_cert_chain()
1877 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001878 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001879 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001880 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001881 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001882 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001883 "Authority Certificate", chain[2].get_subject().CN)
1884
1885
1886 def test_get_peer_cert_chain_none(self):
1887 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001888 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001889 certificate chain.
1890 """
1891 ctx = Context(TLSv1_METHOD)
1892 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1893 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1894 server = Connection(ctx, None)
1895 server.set_accept_state()
1896 client = Connection(Context(TLSv1_METHOD), None)
1897 client.set_connect_state()
1898 self._interactInMemory(client, server)
1899 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001900
1901
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001902 def test_get_session_wrong_args(self):
1903 """
1904 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
1905 with any arguments.
1906 """
1907 ctx = Context(TLSv1_METHOD)
1908 server = Connection(ctx, None)
1909 self.assertRaises(TypeError, server.get_session, 123)
1910 self.assertRaises(TypeError, server.get_session, "hello")
1911 self.assertRaises(TypeError, server.get_session, object())
1912
1913
1914 def test_get_session_unconnected(self):
1915 """
1916 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
1917 an object which has not been connected.
1918 """
1919 ctx = Context(TLSv1_METHOD)
1920 server = Connection(ctx, None)
1921 session = server.get_session()
1922 self.assertIdentical(None, session)
1923
1924
1925 def test_server_get_session(self):
1926 """
1927 On the server side of a connection, :py:obj:`Connection.get_session`
1928 returns a :py:class:`Session` instance representing the SSL session for
1929 that connection.
1930 """
1931 server, client = self._loopback()
1932 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001933 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001934
1935
1936 def test_client_get_session(self):
1937 """
1938 On the client side of a connection, :py:obj:`Connection.get_session`
1939 returns a :py:class:`Session` instance representing the SSL session for
1940 that connection.
1941 """
1942 server, client = self._loopback()
1943 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001944 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001945
1946
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05001947 def test_set_session_wrong_args(self):
1948 """
1949 If called with an object that is not an instance of :py:class:`Session`,
1950 or with other than one argument, :py:obj:`Connection.set_session` raises
1951 :py:obj:`TypeError`.
1952 """
1953 ctx = Context(TLSv1_METHOD)
1954 connection = Connection(ctx, None)
1955 self.assertRaises(TypeError, connection.set_session)
1956 self.assertRaises(TypeError, connection.set_session, 123)
1957 self.assertRaises(TypeError, connection.set_session, "hello")
1958 self.assertRaises(TypeError, connection.set_session, object())
1959 self.assertRaises(
1960 TypeError, connection.set_session, Session(), Session())
1961
1962
1963 def test_client_set_session(self):
1964 """
1965 :py:obj:`Connection.set_session`, when used prior to a connection being
1966 established, accepts a :py:class:`Session` instance and causes an
1967 attempt to re-use the session it represents when the SSL handshake is
1968 performed.
1969 """
1970 key = load_privatekey(FILETYPE_PEM, server_key_pem)
1971 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
1972 ctx = Context(TLSv1_METHOD)
1973 ctx.use_privatekey(key)
1974 ctx.use_certificate(cert)
1975 ctx.set_session_id("unity-test")
1976
1977 def makeServer(socket):
1978 server = Connection(ctx, socket)
1979 server.set_accept_state()
1980 return server
1981
1982 originalServer, originalClient = self._loopback(
1983 serverFactory=makeServer)
1984 originalSession = originalClient.get_session()
1985
1986 def makeClient(socket):
1987 client = self._loopbackClientFactory(socket)
1988 client.set_session(originalSession)
1989 return client
1990 resumedServer, resumedClient = self._loopback(
1991 serverFactory=makeServer,
1992 clientFactory=makeClient)
1993
1994 # This is a proxy: in general, we have no access to any unique
1995 # identifier for the session (new enough versions of OpenSSL expose a
1996 # hash which could be usable, but "new enough" is very, very new).
1997 # Instead, exploit the fact that the master key is re-used if the
1998 # session is re-used. As long as the master key for the two connections
1999 # is the same, the session was re-used!
2000 self.assertEqual(
2001 originalServer.master_key(), resumedServer.master_key())
2002
2003
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002004 def test_set_session_wrong_method(self):
2005 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002006 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
2007 instance associated with a context using a different SSL method than the
2008 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
2009 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002010 """
2011 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2012 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2013 ctx = Context(TLSv1_METHOD)
2014 ctx.use_privatekey(key)
2015 ctx.use_certificate(cert)
2016 ctx.set_session_id("unity-test")
2017
2018 def makeServer(socket):
2019 server = Connection(ctx, socket)
2020 server.set_accept_state()
2021 return server
2022
2023 originalServer, originalClient = self._loopback(
2024 serverFactory=makeServer)
2025 originalSession = originalClient.get_session()
2026
2027 def makeClient(socket):
2028 # Intentionally use a different, incompatible method here.
2029 client = Connection(Context(SSLv3_METHOD), socket)
2030 client.set_connect_state()
2031 client.set_session(originalSession)
2032 return client
2033
2034 self.assertRaises(
2035 Error,
2036 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2037
2038
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002039 def test_wantWriteError(self):
2040 """
2041 :py:obj:`Connection` methods which generate output raise
2042 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2043 fail indicating a should-write state.
2044 """
2045 client_socket, server_socket = socket_pair()
2046 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002047 # anything. Only write a single byte at a time so we can be sure we
2048 # completely fill the buffer. Even though the socket API is allowed to
2049 # signal a short write via its return value it seems this doesn't
2050 # always happen on all platforms (FreeBSD and OS X particular) for the
2051 # very last bit of available buffer space.
2052 msg = b"x"
2053 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002054 try:
2055 client_socket.send(msg)
2056 except error as e:
2057 if e.errno == EWOULDBLOCK:
2058 break
2059 raise
2060 else:
2061 self.fail(
2062 "Failed to fill socket buffer, cannot test BIO want write")
2063
2064 ctx = Context(TLSv1_METHOD)
2065 conn = Connection(ctx, client_socket)
2066 # Client's speak first, so make it an SSL client
2067 conn.set_connect_state()
2068 self.assertRaises(WantWriteError, conn.do_handshake)
2069
2070 # XXX want_read
2071
Fedor Brunner416f4a12014-03-28 13:18:38 +01002072 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002073 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002074 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2075 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002076 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002077 ctx = Context(TLSv1_METHOD)
2078 connection = Connection(ctx, None)
2079 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002080
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002081
Fedor Brunner416f4a12014-03-28 13:18:38 +01002082 def test_get_peer_finished_before_connect(self):
2083 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002084 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2085 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002086 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002087 ctx = Context(TLSv1_METHOD)
2088 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002089 self.assertEqual(connection.get_peer_finished(), None)
2090
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002091
Fedor Brunner416f4a12014-03-28 13:18:38 +01002092 def test_get_finished(self):
2093 """
2094 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002095 message send from client, or server. Finished messages are send during
2096 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002097 """
2098
Fedor Brunner5747b932014-03-05 14:22:34 +01002099 server, client = self._loopback()
2100
2101 self.assertNotEqual(server.get_finished(), None)
2102 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002103
Jean-Paul Calderoned979f232014-03-30 11:58:00 -04002104
Fedor Brunner416f4a12014-03-28 13:18:38 +01002105 def test_get_peer_finished(self):
2106 """
2107 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002108 message received from client, or server. Finished messages are send
2109 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002110 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002111 server, client = self._loopback()
2112
2113 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002114 self.assertTrue(len(server.get_peer_finished()) > 0)
2115
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002116
Fedor Brunner416f4a12014-03-28 13:18:38 +01002117 def test_tls_finished_message_symmetry(self):
2118 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002119 The TLS Finished message send by server must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002120 received by client.
2121
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002122 The TLS Finished message send by client must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002123 received by server.
2124 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002125 server, client = self._loopback()
2126
Fedor Brunner5747b932014-03-05 14:22:34 +01002127 self.assertEqual(server.get_finished(), client.get_peer_finished())
2128 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002129
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002130
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002131 def test_get_cipher_name_before_connect(self):
2132 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002133 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2134 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002135 """
2136 ctx = Context(TLSv1_METHOD)
2137 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002138 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002139
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002140
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002141 def test_get_cipher_name(self):
2142 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002143 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2144 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002145 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002146 server, client = self._loopback()
2147 server_cipher_name, client_cipher_name = \
2148 server.get_cipher_name(), client.get_cipher_name()
2149
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002150 self.assertIsInstance(server_cipher_name, text_type)
2151 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002152
2153 self.assertEqual(server_cipher_name, client_cipher_name)
2154
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002155
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002156 def test_get_cipher_version_before_connect(self):
2157 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002158 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2159 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002160 """
2161 ctx = Context(TLSv1_METHOD)
2162 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002163 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002164
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002165
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002166 def test_get_cipher_version(self):
2167 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002168 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2169 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002170 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002171 server, client = self._loopback()
2172 server_cipher_version, client_cipher_version = \
2173 server.get_cipher_version(), client.get_cipher_version()
2174
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002175 self.assertIsInstance(server_cipher_version, text_type)
2176 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002177
2178 self.assertEqual(server_cipher_version, client_cipher_version)
2179
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002180
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002181 def test_get_cipher_bits_before_connect(self):
2182 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002183 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2184 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002185 """
2186 ctx = Context(TLSv1_METHOD)
2187 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002188 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002189
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002190
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002191 def test_get_cipher_bits(self):
2192 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002193 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2194 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002195 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002196 server, client = self._loopback()
2197 server_cipher_bits, client_cipher_bits = \
2198 server.get_cipher_bits(), client.get_cipher_bits()
2199
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002200 self.assertIsInstance(server_cipher_bits, int)
2201 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002202
2203 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002204
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002205
2206
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002207class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002208 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002209 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002210 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002211 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002212 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002213 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002214 arguments.
2215 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002216 connection = Connection(Context(TLSv1_METHOD), None)
2217 self.assertRaises(TypeError, connection.get_cipher_list, None)
2218
2219
2220 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002221 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002222 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2223 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002224 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002225 connection = Connection(Context(TLSv1_METHOD), None)
2226 ciphers = connection.get_cipher_list()
2227 self.assertTrue(isinstance(ciphers, list))
2228 for cipher in ciphers:
2229 self.assertTrue(isinstance(cipher, str))
2230
2231
2232
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002233class ConnectionSendTests(TestCase, _LoopbackMixin):
2234 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002235 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002236 """
2237 def test_wrong_args(self):
2238 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002239 When called with arguments other than string argument for its first
2240 parameter or more than two arguments, :py:obj:`Connection.send` raises
2241 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002242 """
2243 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002244 self.assertRaises(TypeError, connection.send)
2245 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002246 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002247
2248
2249 def test_short_bytes(self):
2250 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002251 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002252 and returns the number of bytes sent.
2253 """
2254 server, client = self._loopback()
2255 count = server.send(b('xy'))
2256 self.assertEquals(count, 2)
2257 self.assertEquals(client.recv(2), b('xy'))
2258
Abraham Martinef063482015-03-25 14:06:24 +00002259
2260 def test_text(self):
2261 """
2262 When passed a text, :py:obj:`Connection.send` transmits all of it and returns
2263 the number of bytes sent. It also raises a DeprecationWarning.
2264 """
2265 server, client = self._loopback()
2266 with catch_warnings(record=True) as w:
2267 simplefilter("always")
2268 if PY3:
2269 count = server.send(b'xy'.decode())
2270 self.assertTrue("str in buf is no longer accepted, use bytes" in str(w[-1].message))
2271 else:
2272 count = server.send(unicode('xy'))
2273 self.assertTrue("unicode in buf is no longer accepted, use bytes" in str(w[-1].message))
2274 self.assertTrue(issubclass(w[-1].category, DeprecationWarning))
2275 self.assertEquals(count, 2)
2276 self.assertEquals(client.recv(2), b('xy'))
2277
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002278 try:
2279 memoryview
2280 except NameError:
2281 "cannot test sending memoryview without memoryview"
2282 else:
2283 def test_short_memoryview(self):
2284 """
2285 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002286 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002287 bytes sent.
2288 """
2289 server, client = self._loopback()
2290 count = server.send(memoryview(b('xy')))
2291 self.assertEquals(count, 2)
2292 self.assertEquals(client.recv(2), b('xy'))
2293
2294
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002295 try:
2296 buffer
2297 except NameError:
2298 "cannot test sending buffer without buffer"
2299 else:
2300 def test_short_buffer(self):
2301 """
2302 When passed a buffer containing a small number of bytes,
2303 :py:obj:`Connection.send` transmits all of them and returns the number of
2304 bytes sent.
2305 """
2306 server, client = self._loopback()
2307 count = server.send(buffer(b('xy')))
2308 self.assertEquals(count, 2)
2309 self.assertEquals(client.recv(2), b('xy'))
2310
2311
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002312
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002313class ConnectionSendallTests(TestCase, _LoopbackMixin):
2314 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002315 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002316 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002317 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002318 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002319 When called with arguments other than a string argument for its first
2320 parameter or with more than two arguments, :py:obj:`Connection.sendall`
2321 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002322 """
2323 connection = Connection(Context(TLSv1_METHOD), None)
2324 self.assertRaises(TypeError, connection.sendall)
2325 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002326 self.assertRaises(
2327 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002328
2329
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002330 def test_short(self):
2331 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002332 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002333 it.
2334 """
2335 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04002336 server.sendall(b('x'))
2337 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002338
2339
Abraham Martinef063482015-03-25 14:06:24 +00002340 def test_text(self):
2341 """
2342 :py:obj:`Connection.sendall` transmits all the content in the string passed to
2343 it raising a DepreactionWarning in case of this being a text.
2344 """
2345 server, client = self._loopback()
2346 with catch_warnings(record=True) as w:
2347 simplefilter("always")
2348 if PY3:
2349 server.sendall(b'x'.decode())
2350 self.assertTrue("str in buf is no longer accepted, use bytes" in str(w[-1].message))
2351 else:
2352 server.sendall(unicode('x'))
2353 self.assertTrue("unicode in buf is no longer accepted, use bytes" in str(w[-1].message))
2354 self.assertTrue(issubclass(w[-1].category, DeprecationWarning))
2355 self.assertEquals(client.recv(1), b('x'))
2356
2357
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002358 try:
2359 memoryview
2360 except NameError:
2361 "cannot test sending memoryview without memoryview"
2362 else:
2363 def test_short_memoryview(self):
2364 """
2365 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002366 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002367 """
2368 server, client = self._loopback()
2369 server.sendall(memoryview(b('x')))
2370 self.assertEquals(client.recv(1), b('x'))
2371
2372
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002373 try:
2374 buffer
2375 except NameError:
2376 "cannot test sending buffers without buffers"
2377 else:
2378 def test_short_buffers(self):
2379 """
2380 When passed a buffer containing a small number of bytes,
2381 :py:obj:`Connection.sendall` transmits all of them.
2382 """
2383 server, client = self._loopback()
2384 server.sendall(buffer(b('x')))
2385 self.assertEquals(client.recv(1), b('x'))
2386
2387
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002388 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002389 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002390 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002391 it even if this requires multiple calls of an underlying write function.
2392 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002393 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04002394 # Should be enough, underlying SSL_write should only do 16k at a time.
2395 # On Windows, after 32k of bytes the write will block (forever - because
2396 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04002397 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002398 server.sendall(message)
2399 accum = []
2400 received = 0
2401 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04002402 data = client.recv(1024)
2403 accum.append(data)
2404 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04002405 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002406
2407
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002408 def test_closed(self):
2409 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002410 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002411 write error from the low level write call.
2412 """
2413 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04002414 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002415 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02002416 if platform == "win32":
2417 self.assertEqual(exc.args[0], ESHUTDOWN)
2418 else:
2419 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002420
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002421
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002422
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002423class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
2424 """
2425 Tests for SSL renegotiation APIs.
2426 """
2427 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002428 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002429 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002430 arguments.
2431 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002432 connection = Connection(Context(TLSv1_METHOD), None)
2433 self.assertRaises(TypeError, connection.renegotiate, None)
2434
2435
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002436 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002437 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002438 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002439 any arguments.
2440 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002441 connection = Connection(Context(TLSv1_METHOD), None)
2442 self.assertRaises(TypeError, connection.total_renegotiations, None)
2443
2444
2445 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002446 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002447 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002448 renegotiations have happened.
2449 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002450 connection = Connection(Context(TLSv1_METHOD), None)
2451 self.assertEquals(connection.total_renegotiations(), 0)
2452
2453
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002454# def test_renegotiate(self):
2455# """
2456# """
2457# server, client = self._loopback()
2458
2459# server.send("hello world")
2460# self.assertEquals(client.recv(len("hello world")), "hello world")
2461
2462# self.assertEquals(server.total_renegotiations(), 0)
2463# self.assertTrue(server.renegotiate())
2464
2465# server.setblocking(False)
2466# client.setblocking(False)
2467# while server.renegotiate_pending():
2468# client.do_handshake()
2469# server.do_handshake()
2470
2471# self.assertEquals(server.total_renegotiations(), 1)
2472
2473
2474
2475
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002476class ErrorTests(TestCase):
2477 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002478 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002479 """
2480 def test_type(self):
2481 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002482 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002483 """
2484 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05002485 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05002486
2487
2488
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002489class ConstantsTests(TestCase):
2490 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002491 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002492
2493 These are values defined by OpenSSL intended only to be used as flags to
2494 OpenSSL APIs. The only assertions it seems can be made about them is
2495 their values.
2496 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002497 # unittest.TestCase has no skip mechanism
2498 if OP_NO_QUERY_MTU is not None:
2499 def test_op_no_query_mtu(self):
2500 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002501 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002502 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002503 """
2504 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
2505 else:
2506 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002507
2508
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002509 if OP_COOKIE_EXCHANGE is not None:
2510 def test_op_cookie_exchange(self):
2511 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002512 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002513 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002514 """
2515 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
2516 else:
2517 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002518
2519
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002520 if OP_NO_TICKET is not None:
2521 def test_op_no_ticket(self):
2522 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002523 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002524 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002525 """
2526 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04002527 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002528 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05002529
2530
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002531 if OP_NO_COMPRESSION is not None:
2532 def test_op_no_compression(self):
2533 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002534 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
2535 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002536 """
2537 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
2538 else:
2539 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
2540
2541
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002542 def test_sess_cache_off(self):
2543 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002544 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
2545 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002546 """
2547 self.assertEqual(0x0, SESS_CACHE_OFF)
2548
2549
2550 def test_sess_cache_client(self):
2551 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002552 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
2553 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002554 """
2555 self.assertEqual(0x1, SESS_CACHE_CLIENT)
2556
2557
2558 def test_sess_cache_server(self):
2559 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002560 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
2561 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002562 """
2563 self.assertEqual(0x2, SESS_CACHE_SERVER)
2564
2565
2566 def test_sess_cache_both(self):
2567 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002568 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
2569 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002570 """
2571 self.assertEqual(0x3, SESS_CACHE_BOTH)
2572
2573
2574 def test_sess_cache_no_auto_clear(self):
2575 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002576 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
2577 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
2578 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002579 """
2580 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
2581
2582
2583 def test_sess_cache_no_internal_lookup(self):
2584 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002585 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
2586 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
2587 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002588 """
2589 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
2590
2591
2592 def test_sess_cache_no_internal_store(self):
2593 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002594 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
2595 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
2596 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002597 """
2598 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
2599
2600
2601 def test_sess_cache_no_internal(self):
2602 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002603 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
2604 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
2605 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002606 """
2607 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
2608
2609
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04002610
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002611class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05002612 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002613 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05002614 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002615 def _server(self, sock):
2616 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002617 Create a new server-side SSL :py:obj:`Connection` object wrapped around
2618 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002619 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002620 # Create the server side Connection. This is mostly setup boilerplate
2621 # - use TLSv1, use a particular certificate, etc.
2622 server_ctx = Context(TLSv1_METHOD)
2623 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2624 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2625 server_store = server_ctx.get_cert_store()
2626 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2627 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2628 server_ctx.check_privatekey()
2629 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002630 # Here the Connection is actually created. If None is passed as the 2nd
2631 # parameter, it indicates a memory BIO should be created.
2632 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002633 server_conn.set_accept_state()
2634 return server_conn
2635
2636
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002637 def _client(self, sock):
2638 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002639 Create a new client-side SSL :py:obj:`Connection` object wrapped around
2640 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002641 """
2642 # Now create the client side Connection. Similar boilerplate to the
2643 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002644 client_ctx = Context(TLSv1_METHOD)
2645 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2646 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2647 client_store = client_ctx.get_cert_store()
2648 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
2649 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
2650 client_ctx.check_privatekey()
2651 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002652 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002653 client_conn.set_connect_state()
2654 return client_conn
2655
2656
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002657 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002658 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002659 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002660 reading from the output of each and writing those bytes to the input of
2661 the other and in this way establish a connection and exchange
2662 application-level bytes with each other.
2663 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002664 server_conn = self._server(None)
2665 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002666
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002667 # There should be no key or nonces yet.
2668 self.assertIdentical(server_conn.master_key(), None)
2669 self.assertIdentical(server_conn.client_random(), None)
2670 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002671
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002672 # First, the handshake needs to happen. We'll deliver bytes back and
2673 # forth between the client and server until neither of them feels like
2674 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002675 self.assertIdentical(
2676 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002677
2678 # Now that the handshake is done, there should be a key and nonces.
2679 self.assertNotIdentical(server_conn.master_key(), None)
2680 self.assertNotIdentical(server_conn.client_random(), None)
2681 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04002682 self.assertEquals(server_conn.client_random(), client_conn.client_random())
2683 self.assertEquals(server_conn.server_random(), client_conn.server_random())
2684 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
2685 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002686
2687 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002688 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05002689
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002690 server_conn.write(important_message)
2691 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002692 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002693 (client_conn, important_message))
2694
2695 client_conn.write(important_message[::-1])
2696 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002697 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002698 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05002699
2700
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002701 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05002702 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002703 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002704
2705 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09002706 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002707 this test fails, there must be a problem outside the memory BIO
2708 code, as no memory BIO is involved here). Even though this isn't a
2709 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05002710 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04002711 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05002712
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002713 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05002714 client_conn.send(important_message)
2715 msg = server_conn.recv(1024)
2716 self.assertEqual(msg, important_message)
2717
2718 # Again in the other direction, just for fun.
2719 important_message = important_message[::-1]
2720 server_conn.send(important_message)
2721 msg = client_conn.recv(1024)
2722 self.assertEqual(msg, important_message)
2723
2724
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04002725 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05002726 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002727 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
2728 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05002729 """
2730 context = Context(SSLv3_METHOD)
2731 client = socket()
2732 clientSSL = Connection(context, client)
2733 self.assertRaises( TypeError, clientSSL.bio_read, 100)
2734 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04002735 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002736
2737
2738 def test_outgoingOverflow(self):
2739 """
2740 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002741 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002742 returned and that many bytes from the beginning of the input can be
2743 read from the other end of the connection.
2744 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002745 server = self._server(None)
2746 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002747
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002748 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002749
2750 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002751 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002752 # Sanity check. We're trying to test what happens when the entire
2753 # input can't be sent. If the entire input was sent, this test is
2754 # meaningless.
2755 self.assertTrue(sent < size)
2756
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002757 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002758 self.assertIdentical(receiver, server)
2759
2760 # We can rely on all of these bytes being received at once because
2761 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
2762 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002763
2764
2765 def test_shutdown(self):
2766 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002767 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
2768 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002769 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002770 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002771 server.bio_shutdown()
2772 e = self.assertRaises(Error, server.recv, 1024)
2773 # We don't want WantReadError or ZeroReturnError or anything - it's a
2774 # handshake failure.
2775 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002776
2777
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002778 def test_unexpectedEndOfFile(self):
2779 """
2780 If the connection is lost before an orderly SSL shutdown occurs,
2781 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
2782 "Unexpected EOF".
2783 """
2784 server_conn, client_conn = self._loopback()
2785 client_conn.sock_shutdown(SHUT_RDWR)
2786 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
2787 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
2788
2789
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002790 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002791 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002792 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 -04002793
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002794 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002795 before the client and server are connected to each other. This
2796 function should specify a list of CAs for the server to send to the
2797 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09002798 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002799 times.
2800 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002801 server = self._server(None)
2802 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002803 self.assertEqual(client.get_client_ca_list(), [])
2804 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002805 ctx = server.get_context()
2806 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002807 self.assertEqual(client.get_client_ca_list(), [])
2808 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002809 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002810 self.assertEqual(client.get_client_ca_list(), expected)
2811 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002812
2813
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002814 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002815 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002816 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002817 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002818 """
2819 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002820 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
2821 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
2822 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002823
2824
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002825 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002826 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002827 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002828 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09002829 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002830 after the connection is set up.
2831 """
2832 def no_ca(ctx):
2833 ctx.set_client_ca_list([])
2834 return []
2835 self._check_client_ca_list(no_ca)
2836
2837
2838 def test_set_one_ca_list(self):
2839 """
2840 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002841 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002842 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002843 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002844 X509Name after the connection is set up.
2845 """
2846 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2847 cadesc = cacert.get_subject()
2848 def single_ca(ctx):
2849 ctx.set_client_ca_list([cadesc])
2850 return [cadesc]
2851 self._check_client_ca_list(single_ca)
2852
2853
2854 def test_set_multiple_ca_list(self):
2855 """
2856 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002857 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002858 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002859 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002860 X509Names after the connection is set up.
2861 """
2862 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2863 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2864
2865 sedesc = secert.get_subject()
2866 cldesc = clcert.get_subject()
2867
2868 def multiple_ca(ctx):
2869 L = [sedesc, cldesc]
2870 ctx.set_client_ca_list(L)
2871 return L
2872 self._check_client_ca_list(multiple_ca)
2873
2874
2875 def test_reset_ca_list(self):
2876 """
2877 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09002878 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002879 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002880 """
2881 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2882 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2883 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2884
2885 cadesc = cacert.get_subject()
2886 sedesc = secert.get_subject()
2887 cldesc = clcert.get_subject()
2888
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002889 def changed_ca(ctx):
2890 ctx.set_client_ca_list([sedesc, cldesc])
2891 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002892 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002893 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002894
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002895
2896 def test_mutated_ca_list(self):
2897 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002898 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002899 afterwards, this does not affect the list of CA names sent to the
2900 client.
2901 """
2902 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2903 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2904
2905 cadesc = cacert.get_subject()
2906 sedesc = secert.get_subject()
2907
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002908 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002909 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002910 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002911 L.append(sedesc)
2912 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002913 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002914
2915
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002916 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002917 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002918 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002919 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002920 """
2921 ctx = Context(TLSv1_METHOD)
2922 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002923 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002924 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002925 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002926
2927
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002928 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002929 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002930 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09002931 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002932 """
2933 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2934 cadesc = cacert.get_subject()
2935 def single_ca(ctx):
2936 ctx.add_client_ca(cacert)
2937 return [cadesc]
2938 self._check_client_ca_list(single_ca)
2939
2940
2941 def test_multiple_add_client_ca(self):
2942 """
2943 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09002944 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002945 """
2946 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2947 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2948
2949 cadesc = cacert.get_subject()
2950 sedesc = secert.get_subject()
2951
2952 def multiple_ca(ctx):
2953 ctx.add_client_ca(cacert)
2954 ctx.add_client_ca(secert)
2955 return [cadesc, sedesc]
2956 self._check_client_ca_list(multiple_ca)
2957
2958
2959 def test_set_and_add_client_ca(self):
2960 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002961 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
2962 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002963 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002964 """
2965 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2966 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2967 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2968
2969 cadesc = cacert.get_subject()
2970 sedesc = secert.get_subject()
2971 cldesc = clcert.get_subject()
2972
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002973 def mixed_set_add_ca(ctx):
2974 ctx.set_client_ca_list([cadesc, sedesc])
2975 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002976 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002977 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002978
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002979
2980 def test_set_after_add_client_ca(self):
2981 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002982 A call to :py:obj:`Context.set_client_ca_list` after a call to
2983 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002984 call with the names specified by the latter cal.
2985 """
2986 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2987 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2988 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2989
2990 cadesc = cacert.get_subject()
2991 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002992
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002993 def set_replaces_add_ca(ctx):
2994 ctx.add_client_ca(clcert)
2995 ctx.set_client_ca_list([cadesc])
2996 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002997 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002998 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002999
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003000
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003001
3002class ConnectionBIOTests(TestCase):
3003 """
3004 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3005 """
3006 def test_wantReadError(self):
3007 """
3008 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
3009 if there are no bytes available to be read from the BIO.
3010 """
3011 ctx = Context(TLSv1_METHOD)
3012 conn = Connection(ctx, None)
3013 self.assertRaises(WantReadError, conn.bio_read, 1024)
3014
3015
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003016 def test_buffer_size(self):
3017 """
3018 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3019 number of bytes to read and return.
3020 """
3021 ctx = Context(TLSv1_METHOD)
3022 conn = Connection(ctx, None)
3023 conn.set_connect_state()
3024 try:
3025 conn.do_handshake()
3026 except WantReadError:
3027 pass
3028 data = conn.bio_read(2)
3029 self.assertEqual(2, len(data))
3030
3031
3032 if not PY3:
3033 def test_buffer_size_long(self):
3034 """
3035 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3036 :py:obj:`long` as well as :py:obj:`int`.
3037 """
3038 ctx = Context(TLSv1_METHOD)
3039 conn = Connection(ctx, None)
3040 conn.set_connect_state()
3041 try:
3042 conn.do_handshake()
3043 except WantReadError:
3044 pass
3045 data = conn.bio_read(long(2))
3046 self.assertEqual(2, len(data))
3047
3048
3049
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003050
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003051class InfoConstantTests(TestCase):
3052 """
3053 Tests for assorted constants exposed for use in info callbacks.
3054 """
3055 def test_integers(self):
3056 """
3057 All of the info constants are integers.
3058
3059 This is a very weak test. It would be nice to have one that actually
3060 verifies that as certain info events happen, the value passed to the
3061 info callback matches up with the constant exposed by OpenSSL.SSL.
3062 """
3063 for const in [
3064 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3065 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3066 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3067 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3068 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
3069 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
3070
3071 self.assertTrue(isinstance(const, int))
3072
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003073
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003074if __name__ == '__main__':
3075 main()