blob: a45edc26bd619976dab170eed41a40fc29837424 [file] [log] [blame]
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05001# Copyright (C) Jean-Paul Calderone
2# See LICENSE for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04003
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04004"""
Jonathan Ballet648875f2011-07-16 14:14:58 +09005Unit tests for :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04006"""
7
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05008from gc import collect, get_referrers
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02009from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE, ESHUTDOWN
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040010from sys import platform, version_info
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070011from socket import SHUT_RDWR, error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040012from os import makedirs
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040013from os.path import join
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -040014from unittest import main
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040015from weakref import ref
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050016
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -040017from six import PY3, text_type, u
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050018
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040019from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080020from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040021from OpenSSL.crypto import dump_privatekey, load_privatekey
22from OpenSSL.crypto import dump_certificate, load_certificate
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040023from OpenSSL.crypto import get_elliptic_curves
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040024
Jean-Paul Calderoneb41d1f42014-04-17 16:02:04 -040025from OpenSSL.SSL import _lib
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040026from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
27from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040028from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040029from OpenSSL.SSL import (
30 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
31 TLSv1_1_METHOD, TLSv1_2_METHOD)
32from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040033from OpenSSL.SSL import (
34 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040035
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040036from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050037 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
38 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
39 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
40
41from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070042 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050043from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070044 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040045
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050046from OpenSSL.test.util import TestCase, b
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040047from OpenSSL.test.test_crypto import (
48 cleartextCertificatePEM, cleartextPrivateKeyPEM)
49from OpenSSL.test.test_crypto import (
50 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
51 root_cert_pem)
52
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050053try:
54 from OpenSSL.SSL import OP_NO_QUERY_MTU
55except ImportError:
56 OP_NO_QUERY_MTU = None
57try:
58 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
59except ImportError:
60 OP_COOKIE_EXCHANGE = None
61try:
62 from OpenSSL.SSL import OP_NO_TICKET
63except ImportError:
64 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040065
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040066try:
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -040067 from OpenSSL.SSL import OP_NO_COMPRESSION
68except ImportError:
69 OP_NO_COMPRESSION = None
70
71try:
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040072 from OpenSSL.SSL import MODE_RELEASE_BUFFERS
73except ImportError:
74 MODE_RELEASE_BUFFERS = None
75
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040076try:
77 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
78except ImportError:
79 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
80
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040081from OpenSSL.SSL import (
82 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
83 SSL_ST_OK, SSL_ST_RENEGOTIATE,
84 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
85 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
86 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
87 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040088
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040089# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
90# to use)
91dhparam = """\
92-----BEGIN DH PARAMETERS-----
93MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
94-----END DH PARAMETERS-----
95"""
96
97
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040098def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040099 return ok
100
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400101
Rick Deanb1ccd562009-07-09 23:52:39 -0500102def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400103 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400104 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400105 """
106 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500107 port = socket()
108 port.bind(('', 0))
109 port.listen(1)
110 client = socket()
111 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400112 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400113 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500114 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500115
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400116 # Let's pass some unencrypted data to make sure our socket connection is
117 # fine. Just one byte, so we don't have to worry about buffers getting
118 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400119 server.send(b("x"))
120 assert client.recv(1024) == b("x")
121 client.send(b("y"))
122 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500123
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400124 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400125 server.setblocking(False)
126 client.setblocking(False)
127
Rick Deanb1ccd562009-07-09 23:52:39 -0500128 return (server, client)
129
130
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400131
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400132def handshake(client, server):
133 conns = [client, server]
134 while conns:
135 for conn in conns:
136 try:
137 conn.do_handshake()
138 except WantReadError:
139 pass
140 else:
141 conns.remove(conn)
142
143
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400144def _create_certificate_chain():
145 """
146 Construct and return a chain of certificates.
147
148 1. A new self-signed certificate authority certificate (cacert)
149 2. A new intermediate certificate signed by cacert (icert)
150 3. A new server certificate signed by icert (scert)
151 """
152 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
153
154 # Step 1
155 cakey = PKey()
156 cakey.generate_key(TYPE_RSA, 512)
157 cacert = X509()
158 cacert.get_subject().commonName = "Authority Certificate"
159 cacert.set_issuer(cacert.get_subject())
160 cacert.set_pubkey(cakey)
161 cacert.set_notBefore(b("20000101000000Z"))
162 cacert.set_notAfter(b("20200101000000Z"))
163 cacert.add_extensions([caext])
164 cacert.set_serial_number(0)
165 cacert.sign(cakey, "sha1")
166
167 # Step 2
168 ikey = PKey()
169 ikey.generate_key(TYPE_RSA, 512)
170 icert = X509()
171 icert.get_subject().commonName = "Intermediate Certificate"
172 icert.set_issuer(cacert.get_subject())
173 icert.set_pubkey(ikey)
174 icert.set_notBefore(b("20000101000000Z"))
175 icert.set_notAfter(b("20200101000000Z"))
176 icert.add_extensions([caext])
177 icert.set_serial_number(0)
178 icert.sign(cakey, "sha1")
179
180 # Step 3
181 skey = PKey()
182 skey.generate_key(TYPE_RSA, 512)
183 scert = X509()
184 scert.get_subject().commonName = "Server Certificate"
185 scert.set_issuer(icert.get_subject())
186 scert.set_pubkey(skey)
187 scert.set_notBefore(b("20000101000000Z"))
188 scert.set_notAfter(b("20200101000000Z"))
189 scert.add_extensions([
190 X509Extension(b('basicConstraints'), True, b('CA:false'))])
191 scert.set_serial_number(0)
192 scert.sign(ikey, "sha1")
193
194 return [(cakey, cacert), (ikey, icert), (skey, scert)]
195
196
197
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400198class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400199 """
200 Helper mixin which defines methods for creating a connected socket pair and
201 for forcing two connected SSL sockets to talk to each other via memory BIOs.
202 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500203 def _loopbackClientFactory(self, socket):
204 client = Connection(Context(TLSv1_METHOD), socket)
205 client.set_connect_state()
206 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400207
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500208
209 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400210 ctx = Context(TLSv1_METHOD)
211 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
212 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500213 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400214 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500215 return server
216
217
218 def _loopback(self, serverFactory=None, clientFactory=None):
219 if serverFactory is None:
220 serverFactory = self._loopbackServerFactory
221 if clientFactory is None:
222 clientFactory = self._loopbackClientFactory
223
224 (server, client) = socket_pair()
225 server = serverFactory(server)
226 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400227
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400228 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400229
230 server.setblocking(True)
231 client.setblocking(True)
232 return server, client
233
234
235 def _interactInMemory(self, client_conn, server_conn):
236 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900237 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400238 objects. Copy bytes back and forth between their send/receive buffers
239 for as long as there is anything to copy. When there is nothing more
Jonathan Ballet648875f2011-07-16 14:14:58 +0900240 to copy, return :py:obj:`None`. If one of them actually manages to deliver
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400241 some application bytes, return a two-tuple of the connection from which
242 the bytes were read and the bytes themselves.
243 """
244 wrote = True
245 while wrote:
246 # Loop until neither side has anything to say
247 wrote = False
248
249 # Copy stuff from each side's send buffer to the other side's
250 # receive buffer.
251 for (read, write) in [(client_conn, server_conn),
252 (server_conn, client_conn)]:
253
254 # Give the side a chance to generate some more bytes, or
255 # succeed.
256 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400257 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400258 except WantReadError:
259 # It didn't succeed, so we'll hope it generated some
260 # output.
261 pass
262 else:
263 # It did succeed, so we'll stop now and let the caller deal
264 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400265 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400266
267 while True:
268 # Keep copying as long as there's more stuff there.
269 try:
270 dirty = read.bio_read(4096)
271 except WantReadError:
272 # Okay, nothing more waiting to be sent. Stop
273 # processing this send buffer.
274 break
275 else:
276 # Keep track of the fact that someone generated some
277 # output.
278 wrote = True
279 write.bio_write(dirty)
280
281
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400282 def _handshakeInMemory(self, client_conn, server_conn):
Jean-Paul Calderoneb2b40782014-05-06 08:47:40 -0400283 """
284 Perform the TLS handshake between two :py:class:`Connection` instances
285 connected to each other via memory BIOs.
286 """
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400287 client_conn.set_connect_state()
288 server_conn.set_accept_state()
289
290 for conn in [client_conn, server_conn]:
291 try:
292 conn.do_handshake()
293 except WantReadError:
294 pass
295
296 self._interactInMemory(client_conn, server_conn)
297
298
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400299
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400300class VersionTests(TestCase):
301 """
302 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900303 :py:obj:`OpenSSL.SSL.SSLeay_version` and
304 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400305 """
306 def test_OPENSSL_VERSION_NUMBER(self):
307 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900308 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400309 byte and the patch, fix, minor, and major versions in the
310 nibbles above that.
311 """
312 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
313
314
315 def test_SSLeay_version(self):
316 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900317 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400318 one of a number of version strings based on that indicator.
319 """
320 versions = {}
321 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
322 SSLEAY_PLATFORM, SSLEAY_DIR]:
323 version = SSLeay_version(t)
324 versions[version] = t
325 self.assertTrue(isinstance(version, bytes))
326 self.assertEqual(len(versions), 5)
327
328
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400329
330class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400331 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900332 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400333 """
334 def test_method(self):
335 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900336 :py:obj:`Context` can be instantiated with one of :py:obj:`SSLv2_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400337 :py:obj:`SSLv3_METHOD`, :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
338 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400339 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400340 methods = [
341 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
342 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400343 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400344
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400345
346 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
347 for meth in maybe:
348 try:
349 Context(meth)
350 except (Error, ValueError):
351 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
352 # don't. Difficult to say in advance.
353 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400354
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400355 self.assertRaises(TypeError, Context, "")
356 self.assertRaises(ValueError, Context, 10)
357
358
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500359 if not PY3:
360 def test_method_long(self):
361 """
362 On Python 2 :py:class:`Context` accepts values of type
363 :py:obj:`long` as well as :py:obj:`int`.
364 """
365 Context(long(TLSv1_METHOD))
366
367
368
Rick Deane15b1472009-07-09 15:53:42 -0500369 def test_type(self):
370 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900371 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400372 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500373 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400374 self.assertIdentical(Context, ContextType)
375 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500376
377
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400378 def test_use_privatekey(self):
379 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900380 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400381 """
382 key = PKey()
383 key.generate_key(TYPE_RSA, 128)
384 ctx = Context(TLSv1_METHOD)
385 ctx.use_privatekey(key)
386 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400387
388
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800389 def test_use_privatekey_file_missing(self):
390 """
391 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error`
392 when passed the name of a file which does not exist.
393 """
394 ctx = Context(TLSv1_METHOD)
395 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
396
397
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500398 if not PY3:
399 def test_use_privatekey_file_long(self):
400 """
401 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
402 filetype of type :py:obj:`long` as well as :py:obj:`int`.
403 """
404 pemfile = self.mktemp()
405
406 key = PKey()
407 key.generate_key(TYPE_RSA, 128)
408
409 with open(pemfile, "wt") as pem:
410 pem.write(
411 dump_privatekey(FILETYPE_PEM, key).decode("ascii"))
412
413 ctx = Context(TLSv1_METHOD)
414 ctx.use_privatekey_file(pemfile, long(FILETYPE_PEM))
415
416
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800417 def test_use_certificate_wrong_args(self):
418 """
419 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
420 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as an
421 argument.
422 """
423 ctx = Context(TLSv1_METHOD)
424 self.assertRaises(TypeError, ctx.use_certificate)
425 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
426 self.assertRaises(TypeError, ctx.use_certificate, X509(), "hello, world")
427
428
429 def test_use_certificate_uninitialized(self):
430 """
431 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
432 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
433 initialized (ie, which does not actually have any certificate data).
434 """
435 ctx = Context(TLSv1_METHOD)
436 self.assertRaises(Error, ctx.use_certificate, X509())
437
438
439 def test_use_certificate(self):
440 """
441 :py:obj:`Context.use_certificate` sets the certificate which will be
442 used to identify connections created using the context.
443 """
444 # TODO
445 # Hard to assert anything. But we could set a privatekey then ask
446 # OpenSSL if the cert and key agree using check_privatekey. Then as
447 # long as check_privatekey works right we're good...
448 ctx = Context(TLSv1_METHOD)
449 ctx.use_certificate(load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
450
451
452 def test_use_certificate_file_wrong_args(self):
453 """
454 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
455 called with zero arguments or more than two arguments, or if the first
456 argument is not a byte string or the second argumnent is not an integer.
457 """
458 ctx = Context(TLSv1_METHOD)
459 self.assertRaises(TypeError, ctx.use_certificate_file)
460 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile", object())
461 self.assertRaises(
462 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM, object())
463 self.assertRaises(
464 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
465 self.assertRaises(
466 TypeError, ctx.use_certificate_file, b"somefile", object())
467
468
469 def test_use_certificate_file_missing(self):
470 """
471 :py:obj:`Context.use_certificate_file` raises
472 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does not
473 exist.
474 """
475 ctx = Context(TLSv1_METHOD)
476 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
477
478
479 def test_use_certificate_file(self):
480 """
481 :py:obj:`Context.use_certificate` sets the certificate which will be
482 used to identify connections created using the context.
483 """
484 # TODO
485 # Hard to assert anything. But we could set a privatekey then ask
486 # OpenSSL if the cert and key agree using check_privatekey. Then as
487 # long as check_privatekey works right we're good...
488 pem_filename = self.mktemp()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500489 with open(pem_filename, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800490 pem_file.write(cleartextCertificatePEM)
491
492 ctx = Context(TLSv1_METHOD)
493 ctx.use_certificate_file(pem_filename)
494
495
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500496 if not PY3:
497 def test_use_certificate_file_long(self):
498 """
499 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
500 filetype of type :py:obj:`long` as well as :py:obj:`int`.
501 """
502 pem_filename = self.mktemp()
503 with open(pem_filename, "wb") as pem_file:
504 pem_file.write(cleartextCertificatePEM)
505
506 ctx = Context(TLSv1_METHOD)
507 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
508
509
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400510 def test_set_app_data_wrong_args(self):
511 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900512 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called with other than
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400513 one argument.
514 """
515 context = Context(TLSv1_METHOD)
516 self.assertRaises(TypeError, context.set_app_data)
517 self.assertRaises(TypeError, context.set_app_data, None, None)
518
519
520 def test_get_app_data_wrong_args(self):
521 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900522 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400523 arguments.
524 """
525 context = Context(TLSv1_METHOD)
526 self.assertRaises(TypeError, context.get_app_data, None)
527
528
529 def test_app_data(self):
530 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900531 :py:obj:`Context.set_app_data` stores an object for later retrieval using
532 :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400533 """
534 app_data = object()
535 context = Context(TLSv1_METHOD)
536 context.set_app_data(app_data)
537 self.assertIdentical(context.get_app_data(), app_data)
538
539
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400540 def test_set_options_wrong_args(self):
541 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900542 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with the wrong
543 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400544 """
545 context = Context(TLSv1_METHOD)
546 self.assertRaises(TypeError, context.set_options)
547 self.assertRaises(TypeError, context.set_options, None)
548 self.assertRaises(TypeError, context.set_options, 1, None)
549
550
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500551 def test_set_options(self):
552 """
553 :py:obj:`Context.set_options` returns the new options value.
554 """
555 context = Context(TLSv1_METHOD)
556 options = context.set_options(OP_NO_SSLv2)
557 self.assertTrue(OP_NO_SSLv2 & options)
558
559
560 if not PY3:
561 def test_set_options_long(self):
562 """
563 On Python 2 :py:obj:`Context.set_options` accepts values of type
564 :py:obj:`long` as well as :py:obj:`int`.
565 """
566 context = Context(TLSv1_METHOD)
567 options = context.set_options(long(OP_NO_SSLv2))
568 self.assertTrue(OP_NO_SSLv2 & options)
569
570
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300571 def test_set_mode_wrong_args(self):
572 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400573 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with the wrong
574 number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300575 """
576 context = Context(TLSv1_METHOD)
577 self.assertRaises(TypeError, context.set_mode)
578 self.assertRaises(TypeError, context.set_mode, None)
579 self.assertRaises(TypeError, context.set_mode, 1, None)
580
581
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400582 if MODE_RELEASE_BUFFERS is not None:
583 def test_set_mode(self):
584 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400585 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the newly
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400586 set mode.
587 """
588 context = Context(TLSv1_METHOD)
589 self.assertTrue(
590 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500591
592 if not PY3:
593 def test_set_mode_long(self):
594 """
595 On Python 2 :py:obj:`Context.set_mode` accepts values of type
596 :py:obj:`long` as well as :py:obj:`int`.
597 """
598 context = Context(TLSv1_METHOD)
599 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
600 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400601 else:
602 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
603
604
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400605 def test_set_timeout_wrong_args(self):
606 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900607 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with the wrong
608 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400609 """
610 context = Context(TLSv1_METHOD)
611 self.assertRaises(TypeError, context.set_timeout)
612 self.assertRaises(TypeError, context.set_timeout, None)
613 self.assertRaises(TypeError, context.set_timeout, 1, None)
614
615
616 def test_get_timeout_wrong_args(self):
617 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900618 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400619 """
620 context = Context(TLSv1_METHOD)
621 self.assertRaises(TypeError, context.get_timeout, None)
622
623
624 def test_timeout(self):
625 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900626 :py:obj:`Context.set_timeout` sets the session timeout for all connections
627 created using the context object. :py:obj:`Context.get_timeout` retrieves this
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400628 value.
629 """
630 context = Context(TLSv1_METHOD)
631 context.set_timeout(1234)
632 self.assertEquals(context.get_timeout(), 1234)
633
634
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500635 if not PY3:
636 def test_timeout_long(self):
637 """
638 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
639 `long` as well as int.
640 """
641 context = Context(TLSv1_METHOD)
642 context.set_timeout(long(1234))
643 self.assertEquals(context.get_timeout(), 1234)
644
645
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400646 def test_set_verify_depth_wrong_args(self):
647 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900648 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called with the wrong
649 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400650 """
651 context = Context(TLSv1_METHOD)
652 self.assertRaises(TypeError, context.set_verify_depth)
653 self.assertRaises(TypeError, context.set_verify_depth, None)
654 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
655
656
657 def test_get_verify_depth_wrong_args(self):
658 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900659 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400660 """
661 context = Context(TLSv1_METHOD)
662 self.assertRaises(TypeError, context.get_verify_depth, None)
663
664
665 def test_verify_depth(self):
666 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900667 :py:obj:`Context.set_verify_depth` sets the number of certificates in a chain
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400668 to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900669 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400670 """
671 context = Context(TLSv1_METHOD)
672 context.set_verify_depth(11)
673 self.assertEquals(context.get_verify_depth(), 11)
674
675
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500676 if not PY3:
677 def test_verify_depth_long(self):
678 """
679 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
680 type `long` as well as int.
681 """
682 context = Context(TLSv1_METHOD)
683 context.set_verify_depth(long(11))
684 self.assertEquals(context.get_verify_depth(), 11)
685
686
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400687 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400688 """
689 Write a new private key out to a new file, encrypted using the given
690 passphrase. Return the path to the new file.
691 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400692 key = PKey()
693 key.generate_key(TYPE_RSA, 128)
694 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400695 fObj = open(pemFile, 'w')
696 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
697 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400698 fObj.close()
699 return pemFile
700
701
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400702 def test_set_passwd_cb_wrong_args(self):
703 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900704 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called with the
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400705 wrong arguments or with a non-callable first argument.
706 """
707 context = Context(TLSv1_METHOD)
708 self.assertRaises(TypeError, context.set_passwd_cb)
709 self.assertRaises(TypeError, context.set_passwd_cb, None)
710 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
711
712
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400713 def test_set_passwd_cb(self):
714 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900715 :py:obj:`Context.set_passwd_cb` accepts a callable which will be invoked when
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400716 a private key is loaded from an encrypted PEM.
717 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400718 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400719 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400720 calledWith = []
721 def passphraseCallback(maxlen, verify, extra):
722 calledWith.append((maxlen, verify, extra))
723 return passphrase
724 context = Context(TLSv1_METHOD)
725 context.set_passwd_cb(passphraseCallback)
726 context.use_privatekey_file(pemFile)
727 self.assertTrue(len(calledWith), 1)
728 self.assertTrue(isinstance(calledWith[0][0], int))
729 self.assertTrue(isinstance(calledWith[0][1], int))
730 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400731
732
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400733 def test_passwd_callback_exception(self):
734 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900735 :py:obj:`Context.use_privatekey_file` propagates any exception raised by the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400736 passphrase callback.
737 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400738 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400739 def passphraseCallback(maxlen, verify, extra):
740 raise RuntimeError("Sorry, I am a fail.")
741
742 context = Context(TLSv1_METHOD)
743 context.set_passwd_cb(passphraseCallback)
744 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
745
746
747 def test_passwd_callback_false(self):
748 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900749 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400750 passphrase callback returns a false value.
751 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400752 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400753 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500754 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400755
756 context = Context(TLSv1_METHOD)
757 context.set_passwd_cb(passphraseCallback)
758 self.assertRaises(Error, context.use_privatekey_file, pemFile)
759
760
761 def test_passwd_callback_non_string(self):
762 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900763 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400764 passphrase callback returns a true non-string value.
765 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400766 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400767 def passphraseCallback(maxlen, verify, extra):
768 return 10
769
770 context = Context(TLSv1_METHOD)
771 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800772 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400773
774
775 def test_passwd_callback_too_long(self):
776 """
777 If the passphrase returned by the passphrase callback returns a string
778 longer than the indicated maximum length, it is truncated.
779 """
780 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400781 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400782 pemFile = self._write_encrypted_pem(passphrase)
783 def passphraseCallback(maxlen, verify, extra):
784 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400785 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400786
787 context = Context(TLSv1_METHOD)
788 context.set_passwd_cb(passphraseCallback)
789 # This shall succeed because the truncated result is the correct
790 # passphrase.
791 context.use_privatekey_file(pemFile)
792
793
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400794 def test_set_info_callback(self):
795 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900796 :py:obj:`Context.set_info_callback` accepts a callable which will be invoked
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400797 when certain information about an SSL connection is available.
798 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500799 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400800
801 clientSSL = Connection(Context(TLSv1_METHOD), client)
802 clientSSL.set_connect_state()
803
804 called = []
805 def info(conn, where, ret):
806 called.append((conn, where, ret))
807 context = Context(TLSv1_METHOD)
808 context.set_info_callback(info)
809 context.use_certificate(
810 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
811 context.use_privatekey(
812 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
813
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400814 serverSSL = Connection(context, server)
815 serverSSL.set_accept_state()
816
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500817 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400818
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500819 # The callback must always be called with a Connection instance as the
820 # first argument. It would probably be better to split this into
821 # separate tests for client and server side info callbacks so we could
822 # assert it is called with the right Connection instance. It would
823 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500824 notConnections = [
825 conn for (conn, where, ret) in called
826 if not isinstance(conn, Connection)]
827 self.assertEqual(
828 [], notConnections,
829 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400830
831
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400832 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400833 """
834 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400835 its :py:obj:`load_verify_locations` method with the given arguments.
836 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400837 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500838 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400839
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400840 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400841 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400842 # Require that the server certificate verify properly or the
843 # connection will fail.
844 clientContext.set_verify(
845 VERIFY_PEER,
846 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
847
848 clientSSL = Connection(clientContext, client)
849 clientSSL.set_connect_state()
850
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400851 serverContext = Context(TLSv1_METHOD)
852 serverContext.use_certificate(
853 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
854 serverContext.use_privatekey(
855 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
856
857 serverSSL = Connection(serverContext, server)
858 serverSSL.set_accept_state()
859
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400860 # Without load_verify_locations above, the handshake
861 # will fail:
862 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
863 # 'certificate verify failed')]
864 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400865
866 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400867 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400868
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500869
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400870 def test_load_verify_file(self):
871 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900872 :py:obj:`Context.load_verify_locations` accepts a file name and uses the
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400873 certificates within for verification purposes.
874 """
875 cafile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400876 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400877 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400878 fObj.close()
879
880 self._load_verify_locations_test(cafile)
881
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400882
883 def test_load_verify_invalid_file(self):
884 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900885 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when passed a
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400886 non-existent cafile.
887 """
888 clientContext = Context(TLSv1_METHOD)
889 self.assertRaises(
890 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400891
892
893 def test_load_verify_directory(self):
894 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900895 :py:obj:`Context.load_verify_locations` accepts a directory name and uses
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400896 the certificates within for verification purposes.
897 """
898 capath = self.mktemp()
899 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400900 # Hash values computed manually with c_rehash to avoid depending on
901 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
902 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500903 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400904 cafile = join(capath, name)
905 fObj = open(cafile, 'w')
906 fObj.write(cleartextCertificatePEM.decode('ascii'))
907 fObj.close()
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400908
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400909 self._load_verify_locations_test(None, capath)
910
911
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400912 def test_load_verify_locations_wrong_args(self):
913 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900914 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if called with
915 the wrong number of arguments or with non-:py:obj:`str` arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400916 """
917 context = Context(TLSv1_METHOD)
918 self.assertRaises(TypeError, context.load_verify_locations)
919 self.assertRaises(TypeError, context.load_verify_locations, object())
920 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
921 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
922
923
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400924 if platform == "win32":
925 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400926 "See LP#404343 and LP#404344."
927 else:
928 def test_set_default_verify_paths(self):
929 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900930 :py:obj:`Context.set_default_verify_paths` causes the platform-specific CA
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400931 certificate locations to be used for verification purposes.
932 """
933 # Testing this requires a server with a certificate signed by one of
934 # the CAs in the platform CA location. Getting one of those costs
935 # money. Fortunately (or unfortunately, depending on your
936 # perspective), it's easy to think of a public server on the
937 # internet which has such a certificate. Connecting to the network
938 # in a unit test is bad, but it's the only way I can think of to
939 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400940
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400941 # Arg, verisign.com doesn't speak TLSv1
942 context = Context(SSLv3_METHOD)
943 context.set_default_verify_paths()
944 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +0200945 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400946 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400947
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400948 client = socket()
949 client.connect(('verisign.com', 443))
950 clientSSL = Connection(context, client)
951 clientSSL.set_connect_state()
952 clientSSL.do_handshake()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500953 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400954 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400955
956
957 def test_set_default_verify_paths_signature(self):
958 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900959 :py:obj:`Context.set_default_verify_paths` takes no arguments and raises
960 :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400961 """
962 context = Context(TLSv1_METHOD)
963 self.assertRaises(TypeError, context.set_default_verify_paths, None)
964 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
965 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500966
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400967
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500968 def test_add_extra_chain_cert_invalid_cert(self):
969 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900970 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if called with
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500971 other than one argument or if called with an object which is not an
Jonathan Ballet648875f2011-07-16 14:14:58 +0900972 instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500973 """
974 context = Context(TLSv1_METHOD)
975 self.assertRaises(TypeError, context.add_extra_chain_cert)
976 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
977 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
978
979
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400980 def _handshake_test(self, serverContext, clientContext):
981 """
982 Verify that a client and server created with the given contexts can
983 successfully handshake and communicate.
984 """
985 serverSocket, clientSocket = socket_pair()
986
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400987 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400988 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400989
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400990 client = Connection(clientContext, clientSocket)
991 client.set_connect_state()
992
993 # Make them talk to each other.
994 # self._interactInMemory(client, server)
995 for i in range(3):
996 for s in [client, server]:
997 try:
998 s.do_handshake()
999 except WantReadError:
1000 pass
1001
1002
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001003 def test_set_verify_callback_connection_argument(self):
1004 """
1005 The first argument passed to the verify callback is the
1006 :py:class:`Connection` instance for which verification is taking place.
1007 """
1008 serverContext = Context(TLSv1_METHOD)
1009 serverContext.use_privatekey(
1010 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1011 serverContext.use_certificate(
1012 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1013 serverConnection = Connection(serverContext, None)
1014
1015 class VerifyCallback(object):
1016 def callback(self, connection, *args):
1017 self.connection = connection
1018 return 1
1019
1020 verify = VerifyCallback()
1021 clientContext = Context(TLSv1_METHOD)
1022 clientContext.set_verify(VERIFY_PEER, verify.callback)
1023 clientConnection = Connection(clientContext, None)
1024 clientConnection.set_connect_state()
1025
1026 self._handshakeInMemory(clientConnection, serverConnection)
1027
1028 self.assertIdentical(verify.connection, clientConnection)
1029
1030
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001031 def test_set_verify_callback_exception(self):
1032 """
1033 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1034 exception, verification fails and the exception is propagated to the
1035 caller of :py:obj:`Connection.do_handshake`.
1036 """
1037 serverContext = Context(TLSv1_METHOD)
1038 serverContext.use_privatekey(
1039 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1040 serverContext.use_certificate(
1041 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1042
1043 clientContext = Context(TLSv1_METHOD)
1044 def verify_callback(*args):
1045 raise Exception("silly verify failure")
1046 clientContext.set_verify(VERIFY_PEER, verify_callback)
1047
1048 exc = self.assertRaises(
1049 Exception, self._handshake_test, serverContext, clientContext)
1050 self.assertEqual("silly verify failure", str(exc))
1051
1052
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001053 def test_add_extra_chain_cert(self):
1054 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001055 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509` instance to add to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001056 the certificate chain.
1057
Jonathan Ballet648875f2011-07-16 14:14:58 +09001058 See :py:obj:`_create_certificate_chain` for the details of the certificate
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001059 chain tested.
1060
1061 The chain is tested by starting a server with scert and connecting
1062 to it with a client which trusts cacert and requires verification to
1063 succeed.
1064 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001065 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001066 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1067
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001068 # Dump the CA certificate to a file because that's the only way to load
1069 # it as a trusted CA in the client context.
1070 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001071 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001072 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001073 fObj.close()
1074
1075 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001076 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001077 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001078 fObj.close()
1079
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001080 # Create the server context
1081 serverContext = Context(TLSv1_METHOD)
1082 serverContext.use_privatekey(skey)
1083 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001084 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001085 serverContext.add_extra_chain_cert(icert)
1086
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001087 # Create the client
1088 clientContext = Context(TLSv1_METHOD)
1089 clientContext.set_verify(
1090 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001091 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001092
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001093 # Try it out.
1094 self._handshake_test(serverContext, clientContext)
1095
1096
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001097 def test_use_certificate_chain_file(self):
1098 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001099 :py:obj:`Context.use_certificate_chain_file` reads a certificate chain from
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001100 the specified file.
1101
1102 The chain is tested by starting a server with scert and connecting
1103 to it with a client which trusts cacert and requires verification to
1104 succeed.
1105 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001106 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001107 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1108
1109 # Write out the chain file.
1110 chainFile = self.mktemp()
Jean-Paul Calderoned8607982014-01-18 10:30:55 -05001111 fObj = open(chainFile, 'wb')
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001112 # Most specific to least general.
Jean-Paul Calderoned8607982014-01-18 10:30:55 -05001113 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1114 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1115 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001116 fObj.close()
1117
1118 serverContext = Context(TLSv1_METHOD)
1119 serverContext.use_certificate_chain_file(chainFile)
1120 serverContext.use_privatekey(skey)
1121
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001122 fObj = open('ca.pem', 'w')
1123 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001124 fObj.close()
1125
1126 clientContext = Context(TLSv1_METHOD)
1127 clientContext.set_verify(
1128 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001129 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001130
1131 self._handshake_test(serverContext, clientContext)
1132
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001133
1134 def test_use_certificate_chain_file_wrong_args(self):
1135 """
1136 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1137 if passed zero or more than one argument or when passed a non-byte
1138 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error` when
1139 passed a bad chain file name (for example, the name of a file which does
1140 not exist).
1141 """
1142 context = Context(TLSv1_METHOD)
1143 self.assertRaises(TypeError, context.use_certificate_chain_file)
1144 self.assertRaises(TypeError, context.use_certificate_chain_file, object())
1145 self.assertRaises(TypeError, context.use_certificate_chain_file, b"foo", object())
1146
1147 self.assertRaises(Error, context.use_certificate_chain_file, self.mktemp())
1148
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001149 # XXX load_client_ca
1150 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001151
1152 def test_get_verify_mode_wrong_args(self):
1153 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001154 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001155 arguments.
1156 """
1157 context = Context(TLSv1_METHOD)
1158 self.assertRaises(TypeError, context.get_verify_mode, None)
1159
1160
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001161 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001162 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001163 :py:obj:`Context.get_verify_mode` returns the verify mode flags previously
1164 passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001165 """
1166 context = Context(TLSv1_METHOD)
1167 self.assertEquals(context.get_verify_mode(), 0)
1168 context.set_verify(
1169 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1170 self.assertEquals(
1171 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1172
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001173
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001174 if not PY3:
1175 def test_set_verify_mode_long(self):
1176 """
1177 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1178 type :py:obj:`long` as well as :py:obj:`int`.
1179 """
1180 context = Context(TLSv1_METHOD)
1181 self.assertEquals(context.get_verify_mode(), 0)
1182 context.set_verify(
1183 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None)
1184 self.assertEquals(
1185 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1186
1187
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001188 def test_load_tmp_dh_wrong_args(self):
1189 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001190 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
1191 number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001192 """
1193 context = Context(TLSv1_METHOD)
1194 self.assertRaises(TypeError, context.load_tmp_dh)
1195 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1196 self.assertRaises(TypeError, context.load_tmp_dh, object())
1197
1198
1199 def test_load_tmp_dh_missing_file(self):
1200 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001201 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the specified file
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001202 does not exist.
1203 """
1204 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001205 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001206
1207
1208 def test_load_tmp_dh(self):
1209 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001210 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001211 specified file.
1212 """
1213 context = Context(TLSv1_METHOD)
1214 dhfilename = self.mktemp()
1215 dhfile = open(dhfilename, "w")
1216 dhfile.write(dhparam)
1217 dhfile.close()
1218 context.load_tmp_dh(dhfilename)
1219 # XXX What should I assert here? -exarkun
1220
1221
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001222 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001223 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001224 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001225 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001226 """
1227 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001228 for curve in get_elliptic_curves():
1229 # The only easily "assertable" thing is that it does not raise an
1230 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001231 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001232
1233
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001234 def test_set_cipher_list_bytes(self):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001235 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001236 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
1237 ciphers which connections created with the context object will be able
1238 to choose from.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001239 """
1240 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001241 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001242 conn = Connection(context, None)
1243 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001244
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001245
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001246 def test_set_cipher_list_text(self):
1247 """
1248 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
1249 the ciphers which connections created with the context object will be
1250 able to choose from.
1251 """
1252 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -05001253 context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001254 conn = Connection(context, None)
1255 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
1256
1257
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001258 def test_set_cipher_list_wrong_args(self):
1259 """
Jean-Paul Calderone17044832014-01-18 10:20:11 -05001260 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
1261 passed zero arguments or more than one argument or when passed a
1262 non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001263 passed an incorrect cipher list string.
1264 """
1265 context = Context(TLSv1_METHOD)
1266 self.assertRaises(TypeError, context.set_cipher_list)
1267 self.assertRaises(TypeError, context.set_cipher_list, object())
1268 self.assertRaises(TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object())
1269
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001270 self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001271
1272
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001273 def test_set_session_cache_mode_wrong_args(self):
1274 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001275 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1276 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001277 """
1278 context = Context(TLSv1_METHOD)
1279 self.assertRaises(TypeError, context.set_session_cache_mode)
1280 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1281
1282
1283 def test_get_session_cache_mode_wrong_args(self):
1284 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001285 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1286 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001287 """
1288 context = Context(TLSv1_METHOD)
1289 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1290
1291
1292 def test_session_cache_mode(self):
1293 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001294 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1295 cached. The setting can be retrieved via
1296 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001297 """
1298 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001299 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001300 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1301 self.assertEqual(SESS_CACHE_OFF, off)
1302 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1303
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001304 if not PY3:
1305 def test_session_cache_mode_long(self):
1306 """
1307 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1308 of type :py:obj:`long` as well as :py:obj:`int`.
1309 """
1310 context = Context(TLSv1_METHOD)
1311 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1312 self.assertEqual(
1313 SESS_CACHE_BOTH, context.get_session_cache_mode())
1314
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001315
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001316 def test_get_cert_store(self):
1317 """
1318 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store` instance.
1319 """
1320 context = Context(TLSv1_METHOD)
1321 store = context.get_cert_store()
1322 self.assertIsInstance(store, X509Store)
1323
1324
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001325
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001326class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1327 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001328 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
1329 :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001330 """
1331 def test_wrong_args(self):
1332 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001333 :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001334 with other than one argument.
1335 """
1336 context = Context(TLSv1_METHOD)
1337 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1338 self.assertRaises(
1339 TypeError, context.set_tlsext_servername_callback, 1, 2)
1340
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001341
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001342 def test_old_callback_forgotten(self):
1343 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001344 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001345 callback, the one it replaces is dereferenced.
1346 """
1347 def callback(connection):
1348 pass
1349
1350 def replacement(connection):
1351 pass
1352
1353 context = Context(TLSv1_METHOD)
1354 context.set_tlsext_servername_callback(callback)
1355
1356 tracker = ref(callback)
1357 del callback
1358
1359 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001360
1361 # One run of the garbage collector happens to work on CPython. PyPy
1362 # doesn't collect the underlying object until a second run for whatever
1363 # reason. That's fine, it still demonstrates our code has properly
1364 # dropped the reference.
1365 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001366 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001367
1368 callback = tracker()
1369 if callback is not None:
1370 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001371 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001372 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001373
1374
1375 def test_no_servername(self):
1376 """
1377 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001378 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
1379 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001380 """
1381 args = []
1382 def servername(conn):
1383 args.append((conn, conn.get_servername()))
1384 context = Context(TLSv1_METHOD)
1385 context.set_tlsext_servername_callback(servername)
1386
1387 # Lose our reference to it. The Context is responsible for keeping it
1388 # alive now.
1389 del servername
1390 collect()
1391
1392 # Necessary to actually accept the connection
1393 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1394 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1395
1396 # Do a little connection to trigger the logic
1397 server = Connection(context, None)
1398 server.set_accept_state()
1399
1400 client = Connection(Context(TLSv1_METHOD), None)
1401 client.set_connect_state()
1402
1403 self._interactInMemory(server, client)
1404
1405 self.assertEqual([(server, None)], args)
1406
1407
1408 def test_servername(self):
1409 """
1410 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +09001411 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
1412 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001413 """
1414 args = []
1415 def servername(conn):
1416 args.append((conn, conn.get_servername()))
1417 context = Context(TLSv1_METHOD)
1418 context.set_tlsext_servername_callback(servername)
1419
1420 # Necessary to actually accept the connection
1421 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1422 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1423
1424 # Do a little connection to trigger the logic
1425 server = Connection(context, None)
1426 server.set_accept_state()
1427
1428 client = Connection(Context(TLSv1_METHOD), None)
1429 client.set_connect_state()
1430 client.set_tlsext_host_name(b("foo1.example.com"))
1431
1432 self._interactInMemory(server, client)
1433
1434 self.assertEqual([(server, b("foo1.example.com"))], args)
1435
1436
Cory Benfield84a121e2014-03-31 20:30:25 +01001437class NextProtoNegotiationTests(TestCase, _LoopbackMixin):
1438 """
1439 Test for Next Protocol Negotiation in PyOpenSSL.
1440 """
1441 def test_npn_success(self):
Cory Benfieldbe3e7b82014-05-10 09:48:55 +01001442 """
1443 Tests that clients and servers that agree on the negotiated next
1444 protocol can correct establish a connection, and that the agreed
1445 protocol is reported by the connections.
1446 """
1447 advertise_args = []
Cory Benfield84a121e2014-03-31 20:30:25 +01001448 select_args = []
1449 def advertise(conn):
1450 advertise_args.append((conn,))
Cory Benfieldbe3e7b82014-05-10 09:48:55 +01001451 return [b'http/1.1', b'spdy/2']
Cory Benfield84a121e2014-03-31 20:30:25 +01001452 def select(conn, options):
1453 select_args.append((conn, options))
Cory Benfieldbe3e7b82014-05-10 09:48:55 +01001454 return b'spdy/2'
Cory Benfield84a121e2014-03-31 20:30:25 +01001455
1456 server_context = Context(TLSv1_METHOD)
1457 server_context.set_npn_advertise_callback(advertise)
1458
1459 client_context = Context(TLSv1_METHOD)
1460 client_context.set_npn_select_callback(select)
1461
1462 # Necessary to actually accept the connection
1463 server_context.use_privatekey(
1464 load_privatekey(FILETYPE_PEM, server_key_pem))
1465 server_context.use_certificate(
1466 load_certificate(FILETYPE_PEM, server_cert_pem))
1467
1468 # Do a little connection to trigger the logic
1469 server = Connection(server_context, None)
1470 server.set_accept_state()
1471
1472 client = Connection(client_context, None)
1473 client.set_connect_state()
1474
1475 self._interactInMemory(server, client)
1476
1477 self.assertEqual([(server,)], advertise_args)
Cory Benfieldbe3e7b82014-05-10 09:48:55 +01001478 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001479
Cory Benfieldbe3e7b82014-05-10 09:48:55 +01001480 self.assertEqual(server.get_next_proto_negotiated(), b'spdy/2')
1481 self.assertEqual(client.get_next_proto_negotiated(), b'spdy/2')
Cory Benfield84a121e2014-03-31 20:30:25 +01001482
1483
1484 def test_npn_client_fail(self):
Cory Benfieldbe3e7b82014-05-10 09:48:55 +01001485 """
1486 Tests that when clients and servers cannot agree on what protocol to
1487 use next that the TLS connection does not get established.
1488 """
1489 advertise_args = []
Cory Benfield84a121e2014-03-31 20:30:25 +01001490 select_args = []
1491 def advertise(conn):
1492 advertise_args.append((conn,))
Cory Benfieldbe3e7b82014-05-10 09:48:55 +01001493 return [b'http/1.1', b'spdy/2']
Cory Benfield84a121e2014-03-31 20:30:25 +01001494 def select(conn, options):
1495 select_args.append((conn, options))
Cory Benfieldbe3e7b82014-05-10 09:48:55 +01001496 return b''
Cory Benfield84a121e2014-03-31 20:30:25 +01001497
1498 server_context = Context(TLSv1_METHOD)
1499 server_context.set_npn_advertise_callback(advertise)
1500
1501 client_context = Context(TLSv1_METHOD)
1502 client_context.set_npn_select_callback(select)
1503
1504 # Necessary to actually accept the connection
1505 server_context.use_privatekey(
1506 load_privatekey(FILETYPE_PEM, server_key_pem))
1507 server_context.use_certificate(
1508 load_certificate(FILETYPE_PEM, server_cert_pem))
1509
1510 # Do a little connection to trigger the logic
1511 server = Connection(server_context, None)
1512 server.set_accept_state()
1513
1514 client = Connection(client_context, None)
1515 client.set_connect_state()
1516
1517 # If the client doesn't return anything, the connection will fail.
1518 self.assertRaises(Error, self._interactInMemory, server, client)
1519
1520 self.assertEqual([(server,)], advertise_args)
Cory Benfieldbe3e7b82014-05-10 09:48:55 +01001521 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001522
1523
Cory Benfield0ea76e72015-03-22 09:05:28 +00001524 def test_npn_select_error(self):
1525 """
1526 Test that we can handle exceptions in the select callback. If select
1527 fails it should be fatal to the connection.
1528 """
1529 advertise_args = []
1530 def advertise(conn):
1531 advertise_args.append((conn,))
1532 return [b'http/1.1', b'spdy/2']
1533 def select(conn, options):
1534 raise TypeError
1535
1536 server_context = Context(TLSv1_METHOD)
1537 server_context.set_npn_advertise_callback(advertise)
1538
1539 client_context = Context(TLSv1_METHOD)
1540 client_context.set_npn_select_callback(select)
1541
1542 # Necessary to actually accept the connection
1543 server_context.use_privatekey(
1544 load_privatekey(FILETYPE_PEM, server_key_pem))
1545 server_context.use_certificate(
1546 load_certificate(FILETYPE_PEM, server_cert_pem))
1547
1548 # Do a little connection to trigger the logic
1549 server = Connection(server_context, None)
1550 server.set_accept_state()
1551
1552 client = Connection(client_context, None)
1553 client.set_connect_state()
1554
1555 # If the callback throws an exception it should be raised here.
1556 self.assertRaises(TypeError, self._interactInMemory, server, client)
1557 self.assertEqual([(server,)], advertise_args)
1558
1559
1560 def test_npn_advertise_error(self):
1561 """
1562 Test that we can handle exceptions in the advertise callback. If
1563 advertise fails no NPN is advertised to the client.
1564 """
1565 select_args = []
1566 def advertise(conn):
1567 raise TypeError
1568 def select(conn, options):
1569 select_args.append((conn, options))
1570 return b''
1571
1572 server_context = Context(TLSv1_METHOD)
1573 server_context.set_npn_advertise_callback(advertise)
1574
1575 client_context = Context(TLSv1_METHOD)
1576 client_context.set_npn_select_callback(select)
1577
1578 # Necessary to actually accept the connection
1579 server_context.use_privatekey(
1580 load_privatekey(FILETYPE_PEM, server_key_pem))
1581 server_context.use_certificate(
1582 load_certificate(FILETYPE_PEM, server_cert_pem))
1583
1584 # Do a little connection to trigger the logic
1585 server = Connection(server_context, None)
1586 server.set_accept_state()
1587
1588 client = Connection(client_context, None)
1589 client.set_connect_state()
1590
1591 # If the client doesn't return anything, the connection will fail.
1592 self.assertRaises(TypeError, self._interactInMemory, server, client)
1593 self.assertEqual([], select_args)
1594
1595
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001596
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001597class SessionTests(TestCase):
1598 """
1599 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1600 """
1601 def test_construction(self):
1602 """
1603 :py:class:`Session` can be constructed with no arguments, creating a new
1604 instance of that type.
1605 """
1606 new_session = Session()
1607 self.assertTrue(isinstance(new_session, Session))
1608
1609
1610 def test_construction_wrong_args(self):
1611 """
1612 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
1613 is raised.
1614 """
1615 self.assertRaises(TypeError, Session, 123)
1616 self.assertRaises(TypeError, Session, "hello")
1617 self.assertRaises(TypeError, Session, object())
1618
1619
1620
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001621class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05001622 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001623 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001624 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001625 # XXX get_peer_certificate -> None
1626 # XXX sock_shutdown
1627 # XXX master_key -> TypeError
1628 # XXX server_random -> TypeError
1629 # XXX state_string
1630 # XXX connect -> TypeError
1631 # XXX connect_ex -> TypeError
1632 # XXX set_connect_state -> TypeError
1633 # XXX set_accept_state -> TypeError
1634 # XXX renegotiate_pending
1635 # XXX do_handshake -> TypeError
1636 # XXX bio_read -> TypeError
1637 # XXX recv -> TypeError
1638 # XXX send -> TypeError
1639 # XXX bio_write -> TypeError
1640
Rick Deane15b1472009-07-09 15:53:42 -05001641 def test_type(self):
1642 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001643 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001644 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05001645 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001646 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05001647 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001648 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05001649
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001650
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001651 def test_get_context(self):
1652 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001653 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
1654 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001655 """
1656 context = Context(TLSv1_METHOD)
1657 connection = Connection(context, None)
1658 self.assertIdentical(connection.get_context(), context)
1659
1660
1661 def test_get_context_wrong_args(self):
1662 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001663 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001664 arguments.
1665 """
1666 connection = Connection(Context(TLSv1_METHOD), None)
1667 self.assertRaises(TypeError, connection.get_context, None)
1668
1669
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001670 def test_set_context_wrong_args(self):
1671 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001672 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
1673 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001674 than 1.
1675 """
1676 ctx = Context(TLSv1_METHOD)
1677 connection = Connection(ctx, None)
1678 self.assertRaises(TypeError, connection.set_context)
1679 self.assertRaises(TypeError, connection.set_context, object())
1680 self.assertRaises(TypeError, connection.set_context, "hello")
1681 self.assertRaises(TypeError, connection.set_context, 1)
1682 self.assertRaises(TypeError, connection.set_context, 1, 2)
1683 self.assertRaises(
1684 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
1685 self.assertIdentical(ctx, connection.get_context())
1686
1687
1688 def test_set_context(self):
1689 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001690 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001691 for the connection.
1692 """
1693 original = Context(SSLv23_METHOD)
1694 replacement = Context(TLSv1_METHOD)
1695 connection = Connection(original, None)
1696 connection.set_context(replacement)
1697 self.assertIdentical(replacement, connection.get_context())
1698 # Lose our references to the contexts, just in case the Connection isn't
1699 # properly managing its own contributions to their reference counts.
1700 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001701 collect()
1702
1703
1704 def test_set_tlsext_host_name_wrong_args(self):
1705 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001706 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001707 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09001708 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001709 """
1710 conn = Connection(Context(TLSv1_METHOD), None)
1711 self.assertRaises(TypeError, conn.set_tlsext_host_name)
1712 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
1713 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
1714 self.assertRaises(
1715 TypeError, conn.set_tlsext_host_name, b("with\0null"))
1716
1717 if version_info >= (3,):
1718 # On Python 3.x, don't accidentally implicitly convert from text.
1719 self.assertRaises(
1720 TypeError,
1721 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001722
1723
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001724 def test_get_servername_wrong_args(self):
1725 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001726 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001727 arguments.
1728 """
1729 connection = Connection(Context(TLSv1_METHOD), None)
1730 self.assertRaises(TypeError, connection.get_servername, object())
1731 self.assertRaises(TypeError, connection.get_servername, 1)
1732 self.assertRaises(TypeError, connection.get_servername, "hello")
1733
1734
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001735 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001736 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001737 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001738 immediate read.
1739 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001740 connection = Connection(Context(TLSv1_METHOD), None)
1741 self.assertEquals(connection.pending(), 0)
1742
1743
1744 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001745 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001746 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001747 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001748 connection = Connection(Context(TLSv1_METHOD), None)
1749 self.assertRaises(TypeError, connection.pending, None)
1750
1751
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001752 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001753 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001754 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001755 argument or with the wrong number of arguments.
1756 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001757 connection = Connection(Context(TLSv1_METHOD), socket())
1758 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001759 self.assertRaises(TypeError, connection.connect)
1760 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001761
1762
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001763 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001764 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001765 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001766 connect method raises it.
1767 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001768 client = socket()
1769 context = Context(TLSv1_METHOD)
1770 clientSSL = Connection(context, client)
1771 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04001772 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001773
1774
1775 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001776 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001777 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001778 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001779 port = socket()
1780 port.bind(('', 0))
1781 port.listen(3)
1782
1783 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001784 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
1785 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001786
1787
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001788 if platform == "darwin":
1789 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
1790 else:
1791 def test_connect_ex(self):
1792 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001793 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001794 errno instead of raising an exception.
1795 """
1796 port = socket()
1797 port.bind(('', 0))
1798 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001799
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001800 clientSSL = Connection(Context(TLSv1_METHOD), socket())
1801 clientSSL.setblocking(False)
1802 result = clientSSL.connect_ex(port.getsockname())
1803 expected = (EINPROGRESS, EWOULDBLOCK)
1804 self.assertTrue(
1805 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001806
1807
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001808 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001809 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001810 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001811 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001812 connection = Connection(Context(TLSv1_METHOD), socket())
1813 self.assertRaises(TypeError, connection.accept, None)
1814
1815
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001816 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001817 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001818 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
1819 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001820 connection originated from.
1821 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001822 ctx = Context(TLSv1_METHOD)
1823 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1824 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001825 port = socket()
1826 portSSL = Connection(ctx, port)
1827 portSSL.bind(('', 0))
1828 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001829
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001830 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001831
1832 # Calling portSSL.getsockname() here to get the server IP address sounds
1833 # great, but frequently fails on Windows.
1834 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001835
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001836 serverSSL, address = portSSL.accept()
1837
1838 self.assertTrue(isinstance(serverSSL, Connection))
1839 self.assertIdentical(serverSSL.get_context(), ctx)
1840 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001841
1842
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001843 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001844 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001845 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001846 number of arguments or with arguments other than integers.
1847 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001848 connection = Connection(Context(TLSv1_METHOD), None)
1849 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04001850 self.assertRaises(TypeError, connection.get_shutdown, None)
1851 self.assertRaises(TypeError, connection.set_shutdown)
1852 self.assertRaises(TypeError, connection.set_shutdown, None)
1853 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001854
1855
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001856 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001857 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001858 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001859 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001860 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001861 self.assertFalse(server.shutdown())
1862 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001863 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001864 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
1865 client.shutdown()
1866 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
1867 self.assertRaises(ZeroReturnError, server.recv, 1024)
1868 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001869
1870
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001871 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001872 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001873 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001874 process.
1875 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001876 connection = Connection(Context(TLSv1_METHOD), socket())
1877 connection.set_shutdown(RECEIVED_SHUTDOWN)
1878 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1879
1880
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05001881 if not PY3:
1882 def test_set_shutdown_long(self):
1883 """
1884 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
1885 of type :py:obj:`long` as well as :py:obj:`int`.
1886 """
1887 connection = Connection(Context(TLSv1_METHOD), socket())
1888 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
1889 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1890
1891
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001892 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001893 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001894 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
1895 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001896 with any arguments.
1897 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001898 conn = Connection(Context(TLSv1_METHOD), None)
1899 self.assertRaises(TypeError, conn.get_app_data, None)
1900 self.assertRaises(TypeError, conn.set_app_data)
1901 self.assertRaises(TypeError, conn.set_app_data, None, None)
1902
1903
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001904 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001905 """
1906 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001907 :py:obj:`Connection.set_app_data` and later retrieved with
1908 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001909 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001910 conn = Connection(Context(TLSv1_METHOD), None)
1911 app_data = object()
1912 conn.set_app_data(app_data)
1913 self.assertIdentical(conn.get_app_data(), app_data)
1914
1915
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001916 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001917 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001918 :py:obj:`Connection.makefile` is not implemented and calling that method raises
1919 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001920 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001921 conn = Connection(Context(TLSv1_METHOD), None)
1922 self.assertRaises(NotImplementedError, conn.makefile)
1923
1924
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001925 def test_get_peer_cert_chain_wrong_args(self):
1926 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001927 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001928 arguments.
1929 """
1930 conn = Connection(Context(TLSv1_METHOD), None)
1931 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
1932 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
1933 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
1934 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
1935
1936
1937 def test_get_peer_cert_chain(self):
1938 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001939 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001940 the connected server returned for the certification verification.
1941 """
1942 chain = _create_certificate_chain()
1943 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1944
1945 serverContext = Context(TLSv1_METHOD)
1946 serverContext.use_privatekey(skey)
1947 serverContext.use_certificate(scert)
1948 serverContext.add_extra_chain_cert(icert)
1949 serverContext.add_extra_chain_cert(cacert)
1950 server = Connection(serverContext, None)
1951 server.set_accept_state()
1952
1953 # Create the client
1954 clientContext = Context(TLSv1_METHOD)
1955 clientContext.set_verify(VERIFY_NONE, verify_cb)
1956 client = Connection(clientContext, None)
1957 client.set_connect_state()
1958
1959 self._interactInMemory(client, server)
1960
1961 chain = client.get_peer_cert_chain()
1962 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001963 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001964 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001965 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001966 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001967 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001968 "Authority Certificate", chain[2].get_subject().CN)
1969
1970
1971 def test_get_peer_cert_chain_none(self):
1972 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001973 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001974 certificate chain.
1975 """
1976 ctx = Context(TLSv1_METHOD)
1977 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1978 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1979 server = Connection(ctx, None)
1980 server.set_accept_state()
1981 client = Connection(Context(TLSv1_METHOD), None)
1982 client.set_connect_state()
1983 self._interactInMemory(client, server)
1984 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001985
1986
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001987 def test_get_session_wrong_args(self):
1988 """
1989 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
1990 with any arguments.
1991 """
1992 ctx = Context(TLSv1_METHOD)
1993 server = Connection(ctx, None)
1994 self.assertRaises(TypeError, server.get_session, 123)
1995 self.assertRaises(TypeError, server.get_session, "hello")
1996 self.assertRaises(TypeError, server.get_session, object())
1997
1998
1999 def test_get_session_unconnected(self):
2000 """
2001 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
2002 an object which has not been connected.
2003 """
2004 ctx = Context(TLSv1_METHOD)
2005 server = Connection(ctx, None)
2006 session = server.get_session()
2007 self.assertIdentical(None, session)
2008
2009
2010 def test_server_get_session(self):
2011 """
2012 On the server side of a connection, :py:obj:`Connection.get_session`
2013 returns a :py:class:`Session` instance representing the SSL session for
2014 that connection.
2015 """
2016 server, client = self._loopback()
2017 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002018 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002019
2020
2021 def test_client_get_session(self):
2022 """
2023 On the client side of a connection, :py:obj:`Connection.get_session`
2024 returns a :py:class:`Session` instance representing the SSL session for
2025 that connection.
2026 """
2027 server, client = self._loopback()
2028 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002029 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002030
2031
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002032 def test_set_session_wrong_args(self):
2033 """
2034 If called with an object that is not an instance of :py:class:`Session`,
2035 or with other than one argument, :py:obj:`Connection.set_session` raises
2036 :py:obj:`TypeError`.
2037 """
2038 ctx = Context(TLSv1_METHOD)
2039 connection = Connection(ctx, None)
2040 self.assertRaises(TypeError, connection.set_session)
2041 self.assertRaises(TypeError, connection.set_session, 123)
2042 self.assertRaises(TypeError, connection.set_session, "hello")
2043 self.assertRaises(TypeError, connection.set_session, object())
2044 self.assertRaises(
2045 TypeError, connection.set_session, Session(), Session())
2046
2047
2048 def test_client_set_session(self):
2049 """
2050 :py:obj:`Connection.set_session`, when used prior to a connection being
2051 established, accepts a :py:class:`Session` instance and causes an
2052 attempt to re-use the session it represents when the SSL handshake is
2053 performed.
2054 """
2055 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2056 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2057 ctx = Context(TLSv1_METHOD)
2058 ctx.use_privatekey(key)
2059 ctx.use_certificate(cert)
2060 ctx.set_session_id("unity-test")
2061
2062 def makeServer(socket):
2063 server = Connection(ctx, socket)
2064 server.set_accept_state()
2065 return server
2066
2067 originalServer, originalClient = self._loopback(
2068 serverFactory=makeServer)
2069 originalSession = originalClient.get_session()
2070
2071 def makeClient(socket):
2072 client = self._loopbackClientFactory(socket)
2073 client.set_session(originalSession)
2074 return client
2075 resumedServer, resumedClient = self._loopback(
2076 serverFactory=makeServer,
2077 clientFactory=makeClient)
2078
2079 # This is a proxy: in general, we have no access to any unique
2080 # identifier for the session (new enough versions of OpenSSL expose a
2081 # hash which could be usable, but "new enough" is very, very new).
2082 # Instead, exploit the fact that the master key is re-used if the
2083 # session is re-used. As long as the master key for the two connections
2084 # is the same, the session was re-used!
2085 self.assertEqual(
2086 originalServer.master_key(), resumedServer.master_key())
2087
2088
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002089 def test_set_session_wrong_method(self):
2090 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002091 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
2092 instance associated with a context using a different SSL method than the
2093 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
2094 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002095 """
2096 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2097 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2098 ctx = Context(TLSv1_METHOD)
2099 ctx.use_privatekey(key)
2100 ctx.use_certificate(cert)
2101 ctx.set_session_id("unity-test")
2102
2103 def makeServer(socket):
2104 server = Connection(ctx, socket)
2105 server.set_accept_state()
2106 return server
2107
2108 originalServer, originalClient = self._loopback(
2109 serverFactory=makeServer)
2110 originalSession = originalClient.get_session()
2111
2112 def makeClient(socket):
2113 # Intentionally use a different, incompatible method here.
2114 client = Connection(Context(SSLv3_METHOD), socket)
2115 client.set_connect_state()
2116 client.set_session(originalSession)
2117 return client
2118
2119 self.assertRaises(
2120 Error,
2121 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2122
2123
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002124 def test_wantWriteError(self):
2125 """
2126 :py:obj:`Connection` methods which generate output raise
2127 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2128 fail indicating a should-write state.
2129 """
2130 client_socket, server_socket = socket_pair()
2131 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002132 # anything. Only write a single byte at a time so we can be sure we
2133 # completely fill the buffer. Even though the socket API is allowed to
2134 # signal a short write via its return value it seems this doesn't
2135 # always happen on all platforms (FreeBSD and OS X particular) for the
2136 # very last bit of available buffer space.
2137 msg = b"x"
2138 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002139 try:
2140 client_socket.send(msg)
2141 except error as e:
2142 if e.errno == EWOULDBLOCK:
2143 break
2144 raise
2145 else:
2146 self.fail(
2147 "Failed to fill socket buffer, cannot test BIO want write")
2148
2149 ctx = Context(TLSv1_METHOD)
2150 conn = Connection(ctx, client_socket)
2151 # Client's speak first, so make it an SSL client
2152 conn.set_connect_state()
2153 self.assertRaises(WantWriteError, conn.do_handshake)
2154
2155 # XXX want_read
2156
Fedor Brunner416f4a12014-03-28 13:18:38 +01002157 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002158 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002159 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2160 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002161 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002162 ctx = Context(TLSv1_METHOD)
2163 connection = Connection(ctx, None)
2164 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002165
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002166
Fedor Brunner416f4a12014-03-28 13:18:38 +01002167 def test_get_peer_finished_before_connect(self):
2168 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002169 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2170 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002171 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002172 ctx = Context(TLSv1_METHOD)
2173 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002174 self.assertEqual(connection.get_peer_finished(), None)
2175
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002176
Fedor Brunner416f4a12014-03-28 13:18:38 +01002177 def test_get_finished(self):
2178 """
2179 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002180 message send from client, or server. Finished messages are send during
2181 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002182 """
2183
Fedor Brunner5747b932014-03-05 14:22:34 +01002184 server, client = self._loopback()
2185
2186 self.assertNotEqual(server.get_finished(), None)
2187 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002188
Jean-Paul Calderoned979f232014-03-30 11:58:00 -04002189
Fedor Brunner416f4a12014-03-28 13:18:38 +01002190 def test_get_peer_finished(self):
2191 """
2192 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002193 message received from client, or server. Finished messages are send
2194 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002195 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002196 server, client = self._loopback()
2197
2198 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002199 self.assertTrue(len(server.get_peer_finished()) > 0)
2200
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002201
Fedor Brunner416f4a12014-03-28 13:18:38 +01002202 def test_tls_finished_message_symmetry(self):
2203 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002204 The TLS Finished message send by server must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002205 received by client.
2206
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002207 The TLS Finished message send by client must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002208 received by server.
2209 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002210 server, client = self._loopback()
2211
Fedor Brunner5747b932014-03-05 14:22:34 +01002212 self.assertEqual(server.get_finished(), client.get_peer_finished())
2213 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002214
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002215
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002216 def test_get_cipher_name_before_connect(self):
2217 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002218 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2219 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002220 """
2221 ctx = Context(TLSv1_METHOD)
2222 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002223 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002224
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002225
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002226 def test_get_cipher_name(self):
2227 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002228 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2229 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002230 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002231 server, client = self._loopback()
2232 server_cipher_name, client_cipher_name = \
2233 server.get_cipher_name(), client.get_cipher_name()
2234
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002235 self.assertIsInstance(server_cipher_name, text_type)
2236 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002237
2238 self.assertEqual(server_cipher_name, client_cipher_name)
2239
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002240
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002241 def test_get_cipher_version_before_connect(self):
2242 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002243 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2244 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002245 """
2246 ctx = Context(TLSv1_METHOD)
2247 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002248 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002249
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002250
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002251 def test_get_cipher_version(self):
2252 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002253 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2254 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002255 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002256 server, client = self._loopback()
2257 server_cipher_version, client_cipher_version = \
2258 server.get_cipher_version(), client.get_cipher_version()
2259
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002260 self.assertIsInstance(server_cipher_version, text_type)
2261 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002262
2263 self.assertEqual(server_cipher_version, client_cipher_version)
2264
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002265
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002266 def test_get_cipher_bits_before_connect(self):
2267 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002268 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2269 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002270 """
2271 ctx = Context(TLSv1_METHOD)
2272 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002273 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002274
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002275
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002276 def test_get_cipher_bits(self):
2277 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002278 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2279 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002280 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002281 server, client = self._loopback()
2282 server_cipher_bits, client_cipher_bits = \
2283 server.get_cipher_bits(), client.get_cipher_bits()
2284
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002285 self.assertIsInstance(server_cipher_bits, int)
2286 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002287
2288 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002289
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002290
2291
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002292class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002293 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002294 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002295 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002296 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002297 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002298 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002299 arguments.
2300 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002301 connection = Connection(Context(TLSv1_METHOD), None)
2302 self.assertRaises(TypeError, connection.get_cipher_list, None)
2303
2304
2305 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002306 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002307 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2308 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002309 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002310 connection = Connection(Context(TLSv1_METHOD), None)
2311 ciphers = connection.get_cipher_list()
2312 self.assertTrue(isinstance(ciphers, list))
2313 for cipher in ciphers:
2314 self.assertTrue(isinstance(cipher, str))
2315
2316
2317
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002318class ConnectionSendTests(TestCase, _LoopbackMixin):
2319 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002320 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002321 """
2322 def test_wrong_args(self):
2323 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002324 When called with arguments other than string argument for its first
2325 parameter or more than two arguments, :py:obj:`Connection.send` raises
2326 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002327 """
2328 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002329 self.assertRaises(TypeError, connection.send)
2330 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002331 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002332
2333
2334 def test_short_bytes(self):
2335 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002336 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002337 and returns the number of bytes sent.
2338 """
2339 server, client = self._loopback()
2340 count = server.send(b('xy'))
2341 self.assertEquals(count, 2)
2342 self.assertEquals(client.recv(2), b('xy'))
2343
2344 try:
2345 memoryview
2346 except NameError:
2347 "cannot test sending memoryview without memoryview"
2348 else:
2349 def test_short_memoryview(self):
2350 """
2351 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002352 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002353 bytes sent.
2354 """
2355 server, client = self._loopback()
2356 count = server.send(memoryview(b('xy')))
2357 self.assertEquals(count, 2)
2358 self.assertEquals(client.recv(2), b('xy'))
2359
2360
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002361 try:
2362 buffer
2363 except NameError:
2364 "cannot test sending buffer without buffer"
2365 else:
2366 def test_short_buffer(self):
2367 """
2368 When passed a buffer containing a small number of bytes,
2369 :py:obj:`Connection.send` transmits all of them and returns the number of
2370 bytes sent.
2371 """
2372 server, client = self._loopback()
2373 count = server.send(buffer(b('xy')))
2374 self.assertEquals(count, 2)
2375 self.assertEquals(client.recv(2), b('xy'))
2376
2377
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002378
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002379class ConnectionSendallTests(TestCase, _LoopbackMixin):
2380 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002381 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002382 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002383 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002384 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002385 When called with arguments other than a string argument for its first
2386 parameter or with more than two arguments, :py:obj:`Connection.sendall`
2387 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002388 """
2389 connection = Connection(Context(TLSv1_METHOD), None)
2390 self.assertRaises(TypeError, connection.sendall)
2391 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002392 self.assertRaises(
2393 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002394
2395
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002396 def test_short(self):
2397 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002398 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002399 it.
2400 """
2401 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04002402 server.sendall(b('x'))
2403 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002404
2405
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002406 try:
2407 memoryview
2408 except NameError:
2409 "cannot test sending memoryview without memoryview"
2410 else:
2411 def test_short_memoryview(self):
2412 """
2413 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002414 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002415 """
2416 server, client = self._loopback()
2417 server.sendall(memoryview(b('x')))
2418 self.assertEquals(client.recv(1), b('x'))
2419
2420
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002421 try:
2422 buffer
2423 except NameError:
2424 "cannot test sending buffers without buffers"
2425 else:
2426 def test_short_buffers(self):
2427 """
2428 When passed a buffer containing a small number of bytes,
2429 :py:obj:`Connection.sendall` transmits all of them.
2430 """
2431 server, client = self._loopback()
2432 server.sendall(buffer(b('x')))
2433 self.assertEquals(client.recv(1), b('x'))
2434
2435
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002436 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002437 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002438 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002439 it even if this requires multiple calls of an underlying write function.
2440 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002441 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04002442 # Should be enough, underlying SSL_write should only do 16k at a time.
2443 # On Windows, after 32k of bytes the write will block (forever - because
2444 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04002445 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002446 server.sendall(message)
2447 accum = []
2448 received = 0
2449 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04002450 data = client.recv(1024)
2451 accum.append(data)
2452 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04002453 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002454
2455
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002456 def test_closed(self):
2457 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002458 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002459 write error from the low level write call.
2460 """
2461 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04002462 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002463 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02002464 if platform == "win32":
2465 self.assertEqual(exc.args[0], ESHUTDOWN)
2466 else:
2467 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002468
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002469
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002470
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002471class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
2472 """
2473 Tests for SSL renegotiation APIs.
2474 """
2475 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002476 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002477 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002478 arguments.
2479 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002480 connection = Connection(Context(TLSv1_METHOD), None)
2481 self.assertRaises(TypeError, connection.renegotiate, None)
2482
2483
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002484 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002485 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002486 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002487 any arguments.
2488 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002489 connection = Connection(Context(TLSv1_METHOD), None)
2490 self.assertRaises(TypeError, connection.total_renegotiations, None)
2491
2492
2493 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002494 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002495 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002496 renegotiations have happened.
2497 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002498 connection = Connection(Context(TLSv1_METHOD), None)
2499 self.assertEquals(connection.total_renegotiations(), 0)
2500
2501
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002502# def test_renegotiate(self):
2503# """
2504# """
2505# server, client = self._loopback()
2506
2507# server.send("hello world")
2508# self.assertEquals(client.recv(len("hello world")), "hello world")
2509
2510# self.assertEquals(server.total_renegotiations(), 0)
2511# self.assertTrue(server.renegotiate())
2512
2513# server.setblocking(False)
2514# client.setblocking(False)
2515# while server.renegotiate_pending():
2516# client.do_handshake()
2517# server.do_handshake()
2518
2519# self.assertEquals(server.total_renegotiations(), 1)
2520
2521
2522
2523
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002524class ErrorTests(TestCase):
2525 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002526 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002527 """
2528 def test_type(self):
2529 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002530 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002531 """
2532 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05002533 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05002534
2535
2536
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002537class ConstantsTests(TestCase):
2538 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002539 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002540
2541 These are values defined by OpenSSL intended only to be used as flags to
2542 OpenSSL APIs. The only assertions it seems can be made about them is
2543 their values.
2544 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002545 # unittest.TestCase has no skip mechanism
2546 if OP_NO_QUERY_MTU is not None:
2547 def test_op_no_query_mtu(self):
2548 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002549 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002550 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002551 """
2552 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
2553 else:
2554 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002555
2556
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002557 if OP_COOKIE_EXCHANGE is not None:
2558 def test_op_cookie_exchange(self):
2559 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002560 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002561 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002562 """
2563 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
2564 else:
2565 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002566
2567
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002568 if OP_NO_TICKET is not None:
2569 def test_op_no_ticket(self):
2570 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002571 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002572 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002573 """
2574 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04002575 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002576 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05002577
2578
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002579 if OP_NO_COMPRESSION is not None:
2580 def test_op_no_compression(self):
2581 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002582 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
2583 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002584 """
2585 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
2586 else:
2587 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
2588
2589
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002590 def test_sess_cache_off(self):
2591 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002592 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
2593 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002594 """
2595 self.assertEqual(0x0, SESS_CACHE_OFF)
2596
2597
2598 def test_sess_cache_client(self):
2599 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002600 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
2601 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002602 """
2603 self.assertEqual(0x1, SESS_CACHE_CLIENT)
2604
2605
2606 def test_sess_cache_server(self):
2607 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002608 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
2609 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002610 """
2611 self.assertEqual(0x2, SESS_CACHE_SERVER)
2612
2613
2614 def test_sess_cache_both(self):
2615 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002616 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
2617 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002618 """
2619 self.assertEqual(0x3, SESS_CACHE_BOTH)
2620
2621
2622 def test_sess_cache_no_auto_clear(self):
2623 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002624 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
2625 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
2626 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002627 """
2628 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
2629
2630
2631 def test_sess_cache_no_internal_lookup(self):
2632 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002633 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
2634 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
2635 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002636 """
2637 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
2638
2639
2640 def test_sess_cache_no_internal_store(self):
2641 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002642 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
2643 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
2644 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002645 """
2646 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
2647
2648
2649 def test_sess_cache_no_internal(self):
2650 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002651 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
2652 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
2653 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002654 """
2655 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
2656
2657
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04002658
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002659class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05002660 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002661 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05002662 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002663 def _server(self, sock):
2664 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002665 Create a new server-side SSL :py:obj:`Connection` object wrapped around
2666 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002667 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002668 # Create the server side Connection. This is mostly setup boilerplate
2669 # - use TLSv1, use a particular certificate, etc.
2670 server_ctx = Context(TLSv1_METHOD)
2671 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2672 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2673 server_store = server_ctx.get_cert_store()
2674 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2675 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2676 server_ctx.check_privatekey()
2677 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002678 # Here the Connection is actually created. If None is passed as the 2nd
2679 # parameter, it indicates a memory BIO should be created.
2680 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002681 server_conn.set_accept_state()
2682 return server_conn
2683
2684
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002685 def _client(self, sock):
2686 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002687 Create a new client-side SSL :py:obj:`Connection` object wrapped around
2688 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002689 """
2690 # Now create the client side Connection. Similar boilerplate to the
2691 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002692 client_ctx = Context(TLSv1_METHOD)
2693 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2694 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2695 client_store = client_ctx.get_cert_store()
2696 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
2697 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
2698 client_ctx.check_privatekey()
2699 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002700 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002701 client_conn.set_connect_state()
2702 return client_conn
2703
2704
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002705 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002706 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002707 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002708 reading from the output of each and writing those bytes to the input of
2709 the other and in this way establish a connection and exchange
2710 application-level bytes with each other.
2711 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002712 server_conn = self._server(None)
2713 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002714
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002715 # There should be no key or nonces yet.
2716 self.assertIdentical(server_conn.master_key(), None)
2717 self.assertIdentical(server_conn.client_random(), None)
2718 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002719
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002720 # First, the handshake needs to happen. We'll deliver bytes back and
2721 # forth between the client and server until neither of them feels like
2722 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002723 self.assertIdentical(
2724 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002725
2726 # Now that the handshake is done, there should be a key and nonces.
2727 self.assertNotIdentical(server_conn.master_key(), None)
2728 self.assertNotIdentical(server_conn.client_random(), None)
2729 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04002730 self.assertEquals(server_conn.client_random(), client_conn.client_random())
2731 self.assertEquals(server_conn.server_random(), client_conn.server_random())
2732 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
2733 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002734
2735 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002736 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05002737
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002738 server_conn.write(important_message)
2739 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002740 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002741 (client_conn, important_message))
2742
2743 client_conn.write(important_message[::-1])
2744 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002745 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002746 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05002747
2748
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002749 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05002750 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002751 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002752
2753 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09002754 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002755 this test fails, there must be a problem outside the memory BIO
2756 code, as no memory BIO is involved here). Even though this isn't a
2757 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05002758 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04002759 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05002760
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002761 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05002762 client_conn.send(important_message)
2763 msg = server_conn.recv(1024)
2764 self.assertEqual(msg, important_message)
2765
2766 # Again in the other direction, just for fun.
2767 important_message = important_message[::-1]
2768 server_conn.send(important_message)
2769 msg = client_conn.recv(1024)
2770 self.assertEqual(msg, important_message)
2771
2772
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04002773 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05002774 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002775 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
2776 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05002777 """
2778 context = Context(SSLv3_METHOD)
2779 client = socket()
2780 clientSSL = Connection(context, client)
2781 self.assertRaises( TypeError, clientSSL.bio_read, 100)
2782 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04002783 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002784
2785
2786 def test_outgoingOverflow(self):
2787 """
2788 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002789 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002790 returned and that many bytes from the beginning of the input can be
2791 read from the other end of the connection.
2792 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002793 server = self._server(None)
2794 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002795
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002796 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002797
2798 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002799 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002800 # Sanity check. We're trying to test what happens when the entire
2801 # input can't be sent. If the entire input was sent, this test is
2802 # meaningless.
2803 self.assertTrue(sent < size)
2804
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002805 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002806 self.assertIdentical(receiver, server)
2807
2808 # We can rely on all of these bytes being received at once because
2809 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
2810 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002811
2812
2813 def test_shutdown(self):
2814 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002815 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
2816 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002817 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002818 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002819 server.bio_shutdown()
2820 e = self.assertRaises(Error, server.recv, 1024)
2821 # We don't want WantReadError or ZeroReturnError or anything - it's a
2822 # handshake failure.
2823 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002824
2825
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002826 def test_unexpectedEndOfFile(self):
2827 """
2828 If the connection is lost before an orderly SSL shutdown occurs,
2829 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
2830 "Unexpected EOF".
2831 """
2832 server_conn, client_conn = self._loopback()
2833 client_conn.sock_shutdown(SHUT_RDWR)
2834 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
2835 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
2836
2837
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002838 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002839 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002840 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 -04002841
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002842 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002843 before the client and server are connected to each other. This
2844 function should specify a list of CAs for the server to send to the
2845 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09002846 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002847 times.
2848 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002849 server = self._server(None)
2850 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002851 self.assertEqual(client.get_client_ca_list(), [])
2852 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002853 ctx = server.get_context()
2854 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002855 self.assertEqual(client.get_client_ca_list(), [])
2856 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002857 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002858 self.assertEqual(client.get_client_ca_list(), expected)
2859 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002860
2861
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002862 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002863 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002864 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002865 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002866 """
2867 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002868 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
2869 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
2870 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002871
2872
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002873 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002874 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002875 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002876 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09002877 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002878 after the connection is set up.
2879 """
2880 def no_ca(ctx):
2881 ctx.set_client_ca_list([])
2882 return []
2883 self._check_client_ca_list(no_ca)
2884
2885
2886 def test_set_one_ca_list(self):
2887 """
2888 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002889 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002890 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002891 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002892 X509Name after the connection is set up.
2893 """
2894 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2895 cadesc = cacert.get_subject()
2896 def single_ca(ctx):
2897 ctx.set_client_ca_list([cadesc])
2898 return [cadesc]
2899 self._check_client_ca_list(single_ca)
2900
2901
2902 def test_set_multiple_ca_list(self):
2903 """
2904 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002905 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002906 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002907 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002908 X509Names after the connection is set up.
2909 """
2910 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2911 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2912
2913 sedesc = secert.get_subject()
2914 cldesc = clcert.get_subject()
2915
2916 def multiple_ca(ctx):
2917 L = [sedesc, cldesc]
2918 ctx.set_client_ca_list(L)
2919 return L
2920 self._check_client_ca_list(multiple_ca)
2921
2922
2923 def test_reset_ca_list(self):
2924 """
2925 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09002926 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002927 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002928 """
2929 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2930 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2931 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2932
2933 cadesc = cacert.get_subject()
2934 sedesc = secert.get_subject()
2935 cldesc = clcert.get_subject()
2936
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002937 def changed_ca(ctx):
2938 ctx.set_client_ca_list([sedesc, cldesc])
2939 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002940 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002941 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002942
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002943
2944 def test_mutated_ca_list(self):
2945 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002946 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002947 afterwards, this does not affect the list of CA names sent to the
2948 client.
2949 """
2950 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2951 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2952
2953 cadesc = cacert.get_subject()
2954 sedesc = secert.get_subject()
2955
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002956 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002957 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002958 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002959 L.append(sedesc)
2960 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002961 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002962
2963
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002964 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002965 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002966 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002967 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002968 """
2969 ctx = Context(TLSv1_METHOD)
2970 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002971 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002972 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002973 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002974
2975
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002976 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002977 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002978 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09002979 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002980 """
2981 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2982 cadesc = cacert.get_subject()
2983 def single_ca(ctx):
2984 ctx.add_client_ca(cacert)
2985 return [cadesc]
2986 self._check_client_ca_list(single_ca)
2987
2988
2989 def test_multiple_add_client_ca(self):
2990 """
2991 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09002992 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002993 """
2994 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2995 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2996
2997 cadesc = cacert.get_subject()
2998 sedesc = secert.get_subject()
2999
3000 def multiple_ca(ctx):
3001 ctx.add_client_ca(cacert)
3002 ctx.add_client_ca(secert)
3003 return [cadesc, sedesc]
3004 self._check_client_ca_list(multiple_ca)
3005
3006
3007 def test_set_and_add_client_ca(self):
3008 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003009 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
3010 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003011 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003012 """
3013 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3014 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3015 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3016
3017 cadesc = cacert.get_subject()
3018 sedesc = secert.get_subject()
3019 cldesc = clcert.get_subject()
3020
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003021 def mixed_set_add_ca(ctx):
3022 ctx.set_client_ca_list([cadesc, sedesc])
3023 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003024 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003025 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003026
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003027
3028 def test_set_after_add_client_ca(self):
3029 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003030 A call to :py:obj:`Context.set_client_ca_list` after a call to
3031 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003032 call with the names specified by the latter cal.
3033 """
3034 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3035 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3036 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3037
3038 cadesc = cacert.get_subject()
3039 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003040
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003041 def set_replaces_add_ca(ctx):
3042 ctx.add_client_ca(clcert)
3043 ctx.set_client_ca_list([cadesc])
3044 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003045 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003046 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003047
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003048
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003049
3050class ConnectionBIOTests(TestCase):
3051 """
3052 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3053 """
3054 def test_wantReadError(self):
3055 """
3056 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
3057 if there are no bytes available to be read from the BIO.
3058 """
3059 ctx = Context(TLSv1_METHOD)
3060 conn = Connection(ctx, None)
3061 self.assertRaises(WantReadError, conn.bio_read, 1024)
3062
3063
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003064 def test_buffer_size(self):
3065 """
3066 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3067 number of bytes to read and return.
3068 """
3069 ctx = Context(TLSv1_METHOD)
3070 conn = Connection(ctx, None)
3071 conn.set_connect_state()
3072 try:
3073 conn.do_handshake()
3074 except WantReadError:
3075 pass
3076 data = conn.bio_read(2)
3077 self.assertEqual(2, len(data))
3078
3079
3080 if not PY3:
3081 def test_buffer_size_long(self):
3082 """
3083 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3084 :py:obj:`long` as well as :py:obj:`int`.
3085 """
3086 ctx = Context(TLSv1_METHOD)
3087 conn = Connection(ctx, None)
3088 conn.set_connect_state()
3089 try:
3090 conn.do_handshake()
3091 except WantReadError:
3092 pass
3093 data = conn.bio_read(long(2))
3094 self.assertEqual(2, len(data))
3095
3096
3097
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003098
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003099class InfoConstantTests(TestCase):
3100 """
3101 Tests for assorted constants exposed for use in info callbacks.
3102 """
3103 def test_integers(self):
3104 """
3105 All of the info constants are integers.
3106
3107 This is a very weak test. It would be nice to have one that actually
3108 verifies that as certain info events happen, the value passed to the
3109 info callback matches up with the constant exposed by OpenSSL.SSL.
3110 """
3111 for const in [
3112 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3113 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3114 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3115 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3116 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
3117 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
3118
3119 self.assertTrue(isinstance(const, int))
3120
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003121
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003122if __name__ == '__main__':
3123 main()