blob: 344ae764ee5d92d3fc02f8ae01d3d465e3044946 [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 Calderone210c0f32015-04-12 09:20:31 -040010from sys import platform, version_info, getfilesystemencoding
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 Calderoneaac43a32015-04-12 09:51:21 -040017from six import PY3, binary_type, 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 Calderone9f2e38e2011-04-14 09:36:55 -040025from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
26from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040027from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040028from OpenSSL.SSL import (
29 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
30 TLSv1_1_METHOD, TLSv1_2_METHOD)
31from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040032from OpenSSL.SSL import (
33 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040034
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040035from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050036 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
37 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
38 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
39
40from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070041 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050042from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070043 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040044
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -040045from OpenSSL.test.util import NON_ASCII, TestCase, b
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040046from OpenSSL.test.test_crypto import (
47 cleartextCertificatePEM, cleartextPrivateKeyPEM)
48from OpenSSL.test.test_crypto import (
49 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
50 root_cert_pem)
51
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050052try:
53 from OpenSSL.SSL import OP_NO_QUERY_MTU
54except ImportError:
55 OP_NO_QUERY_MTU = None
56try:
57 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
58except ImportError:
59 OP_COOKIE_EXCHANGE = None
60try:
61 from OpenSSL.SSL import OP_NO_TICKET
62except ImportError:
63 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040064
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040065try:
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -040066 from OpenSSL.SSL import OP_NO_COMPRESSION
67except ImportError:
68 OP_NO_COMPRESSION = None
69
70try:
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040071 from OpenSSL.SSL import MODE_RELEASE_BUFFERS
72except ImportError:
73 MODE_RELEASE_BUFFERS = None
74
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040075try:
76 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
77except ImportError:
78 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
79
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040080from OpenSSL.SSL import (
81 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
82 SSL_ST_OK, SSL_ST_RENEGOTIATE,
83 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
84 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
85 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
86 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040087
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040088# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
89# to use)
90dhparam = """\
91-----BEGIN DH PARAMETERS-----
92MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
93-----END DH PARAMETERS-----
94"""
95
96
Jean-Paul Calderone05826732015-04-12 11:38:49 -040097def join_bytes_or_unicode(prefix, suffix):
98 """
99 Join two path components of either ``bytes`` or ``unicode``.
100
101 The return type is the same as the type of ``prefix``.
102 """
103 # If the types are the same, nothing special is necessary.
104 if type(prefix) == type(suffix):
105 return join(prefix, suffix)
106
107 # Otherwise, coerce suffix to the type of prefix.
108 if isinstance(prefix, text_type):
109 return join(prefix, suffix.decode(getfilesystemencoding()))
110 else:
111 return join(prefix, suffix.encode(getfilesystemencoding()))
112
113
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400114def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400115 return ok
116
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400117
Rick Deanb1ccd562009-07-09 23:52:39 -0500118def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400119 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400120 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400121 """
122 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500123 port = socket()
124 port.bind(('', 0))
125 port.listen(1)
126 client = socket()
127 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400128 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400129 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500130 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500131
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400132 # Let's pass some unencrypted data to make sure our socket connection is
133 # fine. Just one byte, so we don't have to worry about buffers getting
134 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400135 server.send(b("x"))
136 assert client.recv(1024) == b("x")
137 client.send(b("y"))
138 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500139
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400140 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400141 server.setblocking(False)
142 client.setblocking(False)
143
Rick Deanb1ccd562009-07-09 23:52:39 -0500144 return (server, client)
145
146
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400147
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400148def handshake(client, server):
149 conns = [client, server]
150 while conns:
151 for conn in conns:
152 try:
153 conn.do_handshake()
154 except WantReadError:
155 pass
156 else:
157 conns.remove(conn)
158
159
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400160def _create_certificate_chain():
161 """
162 Construct and return a chain of certificates.
163
164 1. A new self-signed certificate authority certificate (cacert)
165 2. A new intermediate certificate signed by cacert (icert)
166 3. A new server certificate signed by icert (scert)
167 """
168 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
169
170 # Step 1
171 cakey = PKey()
172 cakey.generate_key(TYPE_RSA, 512)
173 cacert = X509()
174 cacert.get_subject().commonName = "Authority Certificate"
175 cacert.set_issuer(cacert.get_subject())
176 cacert.set_pubkey(cakey)
177 cacert.set_notBefore(b("20000101000000Z"))
178 cacert.set_notAfter(b("20200101000000Z"))
179 cacert.add_extensions([caext])
180 cacert.set_serial_number(0)
181 cacert.sign(cakey, "sha1")
182
183 # Step 2
184 ikey = PKey()
185 ikey.generate_key(TYPE_RSA, 512)
186 icert = X509()
187 icert.get_subject().commonName = "Intermediate Certificate"
188 icert.set_issuer(cacert.get_subject())
189 icert.set_pubkey(ikey)
190 icert.set_notBefore(b("20000101000000Z"))
191 icert.set_notAfter(b("20200101000000Z"))
192 icert.add_extensions([caext])
193 icert.set_serial_number(0)
194 icert.sign(cakey, "sha1")
195
196 # Step 3
197 skey = PKey()
198 skey.generate_key(TYPE_RSA, 512)
199 scert = X509()
200 scert.get_subject().commonName = "Server Certificate"
201 scert.set_issuer(icert.get_subject())
202 scert.set_pubkey(skey)
203 scert.set_notBefore(b("20000101000000Z"))
204 scert.set_notAfter(b("20200101000000Z"))
205 scert.add_extensions([
206 X509Extension(b('basicConstraints'), True, b('CA:false'))])
207 scert.set_serial_number(0)
208 scert.sign(ikey, "sha1")
209
210 return [(cakey, cacert), (ikey, icert), (skey, scert)]
211
212
213
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400214class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400215 """
216 Helper mixin which defines methods for creating a connected socket pair and
217 for forcing two connected SSL sockets to talk to each other via memory BIOs.
218 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500219 def _loopbackClientFactory(self, socket):
220 client = Connection(Context(TLSv1_METHOD), socket)
221 client.set_connect_state()
222 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400223
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500224
225 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400226 ctx = Context(TLSv1_METHOD)
227 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
228 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500229 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400230 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500231 return server
232
233
234 def _loopback(self, serverFactory=None, clientFactory=None):
235 if serverFactory is None:
236 serverFactory = self._loopbackServerFactory
237 if clientFactory is None:
238 clientFactory = self._loopbackClientFactory
239
240 (server, client) = socket_pair()
241 server = serverFactory(server)
242 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400243
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400244 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400245
246 server.setblocking(True)
247 client.setblocking(True)
248 return server, client
249
250
251 def _interactInMemory(self, client_conn, server_conn):
252 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900253 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400254 objects. Copy bytes back and forth between their send/receive buffers
255 for as long as there is anything to copy. When there is nothing more
Jonathan Ballet648875f2011-07-16 14:14:58 +0900256 to copy, return :py:obj:`None`. If one of them actually manages to deliver
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400257 some application bytes, return a two-tuple of the connection from which
258 the bytes were read and the bytes themselves.
259 """
260 wrote = True
261 while wrote:
262 # Loop until neither side has anything to say
263 wrote = False
264
265 # Copy stuff from each side's send buffer to the other side's
266 # receive buffer.
267 for (read, write) in [(client_conn, server_conn),
268 (server_conn, client_conn)]:
269
270 # Give the side a chance to generate some more bytes, or
271 # succeed.
272 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400273 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400274 except WantReadError:
275 # It didn't succeed, so we'll hope it generated some
276 # output.
277 pass
278 else:
279 # It did succeed, so we'll stop now and let the caller deal
280 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400281 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400282
283 while True:
284 # Keep copying as long as there's more stuff there.
285 try:
286 dirty = read.bio_read(4096)
287 except WantReadError:
288 # Okay, nothing more waiting to be sent. Stop
289 # processing this send buffer.
290 break
291 else:
292 # Keep track of the fact that someone generated some
293 # output.
294 wrote = True
295 write.bio_write(dirty)
296
297
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400298 def _handshakeInMemory(self, client_conn, server_conn):
Jean-Paul Calderoneb2b40782014-05-06 08:47:40 -0400299 """
300 Perform the TLS handshake between two :py:class:`Connection` instances
301 connected to each other via memory BIOs.
302 """
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400303 client_conn.set_connect_state()
304 server_conn.set_accept_state()
305
306 for conn in [client_conn, server_conn]:
307 try:
308 conn.do_handshake()
309 except WantReadError:
310 pass
311
312 self._interactInMemory(client_conn, server_conn)
313
314
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400315
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400316class VersionTests(TestCase):
317 """
318 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900319 :py:obj:`OpenSSL.SSL.SSLeay_version` and
320 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400321 """
322 def test_OPENSSL_VERSION_NUMBER(self):
323 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900324 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400325 byte and the patch, fix, minor, and major versions in the
326 nibbles above that.
327 """
328 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
329
330
331 def test_SSLeay_version(self):
332 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900333 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400334 one of a number of version strings based on that indicator.
335 """
336 versions = {}
337 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
338 SSLEAY_PLATFORM, SSLEAY_DIR]:
339 version = SSLeay_version(t)
340 versions[version] = t
341 self.assertTrue(isinstance(version, bytes))
342 self.assertEqual(len(versions), 5)
343
344
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400345
346class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400347 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900348 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400349 """
350 def test_method(self):
351 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900352 :py:obj:`Context` can be instantiated with one of :py:obj:`SSLv2_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400353 :py:obj:`SSLv3_METHOD`, :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
354 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400355 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400356 methods = [
357 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
358 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400359 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400360
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400361
362 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
363 for meth in maybe:
364 try:
365 Context(meth)
366 except (Error, ValueError):
367 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
368 # don't. Difficult to say in advance.
369 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400370
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400371 self.assertRaises(TypeError, Context, "")
372 self.assertRaises(ValueError, Context, 10)
373
374
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500375 if not PY3:
376 def test_method_long(self):
377 """
378 On Python 2 :py:class:`Context` accepts values of type
379 :py:obj:`long` as well as :py:obj:`int`.
380 """
381 Context(long(TLSv1_METHOD))
382
383
384
Rick Deane15b1472009-07-09 15:53:42 -0500385 def test_type(self):
386 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900387 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400388 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500389 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400390 self.assertIdentical(Context, ContextType)
391 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500392
393
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400394 def test_use_privatekey(self):
395 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900396 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400397 """
398 key = PKey()
399 key.generate_key(TYPE_RSA, 128)
400 ctx = Context(TLSv1_METHOD)
401 ctx.use_privatekey(key)
402 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400403
404
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800405 def test_use_privatekey_file_missing(self):
406 """
407 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error`
408 when passed the name of a file which does not exist.
409 """
410 ctx = Context(TLSv1_METHOD)
411 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
412
413
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400414 def _use_privatekey_file_test(self, pemfile, filetype):
415 """
416 Verify that calling ``Context.use_privatekey_file`` with the given
417 arguments does not raise an exception.
418 """
419 key = PKey()
420 key.generate_key(TYPE_RSA, 128)
421
422 with open(pemfile, "wt") as pem:
423 pem.write(
424 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
425 )
426
427 ctx = Context(TLSv1_METHOD)
428 ctx.use_privatekey_file(pemfile, filetype)
429
430
431 def test_use_privatekey_file_bytes(self):
432 """
433 A private key can be specified from a file by passing a ``bytes``
434 instance giving the file name to ``Context.use_privatekey_file``.
435 """
436 self._use_privatekey_file_test(
437 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
438 FILETYPE_PEM,
439 )
440
441
442 def test_use_privatekey_file_unicode(self):
443 """
444 A private key can be specified from a file by passing a ``unicode``
445 instance giving the file name to ``Context.use_privatekey_file``.
446 """
447 self._use_privatekey_file_test(
448 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
449 FILETYPE_PEM,
450 )
451
452
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500453 if not PY3:
454 def test_use_privatekey_file_long(self):
455 """
456 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
457 filetype of type :py:obj:`long` as well as :py:obj:`int`.
458 """
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400459 self._use_privatekey_file_test(self.mktemp(), long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500460
461
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800462 def test_use_certificate_wrong_args(self):
463 """
464 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
465 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as an
466 argument.
467 """
468 ctx = Context(TLSv1_METHOD)
469 self.assertRaises(TypeError, ctx.use_certificate)
470 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
471 self.assertRaises(TypeError, ctx.use_certificate, X509(), "hello, world")
472
473
474 def test_use_certificate_uninitialized(self):
475 """
476 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
477 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
478 initialized (ie, which does not actually have any certificate data).
479 """
480 ctx = Context(TLSv1_METHOD)
481 self.assertRaises(Error, ctx.use_certificate, X509())
482
483
484 def test_use_certificate(self):
485 """
486 :py:obj:`Context.use_certificate` sets the certificate which will be
487 used to identify connections created using the context.
488 """
489 # TODO
490 # Hard to assert anything. But we could set a privatekey then ask
491 # OpenSSL if the cert and key agree using check_privatekey. Then as
492 # long as check_privatekey works right we're good...
493 ctx = Context(TLSv1_METHOD)
494 ctx.use_certificate(load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
495
496
497 def test_use_certificate_file_wrong_args(self):
498 """
499 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
500 called with zero arguments or more than two arguments, or if the first
501 argument is not a byte string or the second argumnent is not an integer.
502 """
503 ctx = Context(TLSv1_METHOD)
504 self.assertRaises(TypeError, ctx.use_certificate_file)
505 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile", object())
506 self.assertRaises(
507 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM, object())
508 self.assertRaises(
509 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
510 self.assertRaises(
511 TypeError, ctx.use_certificate_file, b"somefile", object())
512
513
514 def test_use_certificate_file_missing(self):
515 """
516 :py:obj:`Context.use_certificate_file` raises
517 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does not
518 exist.
519 """
520 ctx = Context(TLSv1_METHOD)
521 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
522
523
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400524 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800525 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400526 Verify that calling ``Context.use_certificate_file`` with the given
527 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800528 """
529 # TODO
530 # Hard to assert anything. But we could set a privatekey then ask
531 # OpenSSL if the cert and key agree using check_privatekey. Then as
532 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400533 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800534 pem_file.write(cleartextCertificatePEM)
535
536 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400537 ctx.use_certificate_file(certificate_file)
538
539
540 def test_use_certificate_file_bytes(self):
541 """
542 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
543 ``bytes`` filename) which will be used to identify connections created
544 using the context.
545 """
546 filename = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
547 self._use_certificate_file_test(filename)
548
549
550 def test_use_certificate_file_unicode(self):
551 """
552 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
553 ``bytes`` filename) which will be used to identify connections created
554 using the context.
555 """
556 filename = self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
557 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800558
559
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500560 if not PY3:
561 def test_use_certificate_file_long(self):
562 """
563 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
564 filetype of type :py:obj:`long` as well as :py:obj:`int`.
565 """
566 pem_filename = self.mktemp()
567 with open(pem_filename, "wb") as pem_file:
568 pem_file.write(cleartextCertificatePEM)
569
570 ctx = Context(TLSv1_METHOD)
571 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
572
573
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400574 def test_set_app_data_wrong_args(self):
575 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900576 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called with other than
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400577 one argument.
578 """
579 context = Context(TLSv1_METHOD)
580 self.assertRaises(TypeError, context.set_app_data)
581 self.assertRaises(TypeError, context.set_app_data, None, None)
582
583
584 def test_get_app_data_wrong_args(self):
585 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900586 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400587 arguments.
588 """
589 context = Context(TLSv1_METHOD)
590 self.assertRaises(TypeError, context.get_app_data, None)
591
592
593 def test_app_data(self):
594 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900595 :py:obj:`Context.set_app_data` stores an object for later retrieval using
596 :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400597 """
598 app_data = object()
599 context = Context(TLSv1_METHOD)
600 context.set_app_data(app_data)
601 self.assertIdentical(context.get_app_data(), app_data)
602
603
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400604 def test_set_options_wrong_args(self):
605 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900606 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with the wrong
607 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400608 """
609 context = Context(TLSv1_METHOD)
610 self.assertRaises(TypeError, context.set_options)
611 self.assertRaises(TypeError, context.set_options, None)
612 self.assertRaises(TypeError, context.set_options, 1, None)
613
614
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500615 def test_set_options(self):
616 """
617 :py:obj:`Context.set_options` returns the new options value.
618 """
619 context = Context(TLSv1_METHOD)
620 options = context.set_options(OP_NO_SSLv2)
621 self.assertTrue(OP_NO_SSLv2 & options)
622
623
624 if not PY3:
625 def test_set_options_long(self):
626 """
627 On Python 2 :py:obj:`Context.set_options` accepts values of type
628 :py:obj:`long` as well as :py:obj:`int`.
629 """
630 context = Context(TLSv1_METHOD)
631 options = context.set_options(long(OP_NO_SSLv2))
632 self.assertTrue(OP_NO_SSLv2 & options)
633
634
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300635 def test_set_mode_wrong_args(self):
636 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400637 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with the wrong
638 number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300639 """
640 context = Context(TLSv1_METHOD)
641 self.assertRaises(TypeError, context.set_mode)
642 self.assertRaises(TypeError, context.set_mode, None)
643 self.assertRaises(TypeError, context.set_mode, 1, None)
644
645
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400646 if MODE_RELEASE_BUFFERS is not None:
647 def test_set_mode(self):
648 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400649 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the newly
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400650 set mode.
651 """
652 context = Context(TLSv1_METHOD)
653 self.assertTrue(
654 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500655
656 if not PY3:
657 def test_set_mode_long(self):
658 """
659 On Python 2 :py:obj:`Context.set_mode` accepts values of type
660 :py:obj:`long` as well as :py:obj:`int`.
661 """
662 context = Context(TLSv1_METHOD)
663 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
664 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400665 else:
666 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
667
668
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400669 def test_set_timeout_wrong_args(self):
670 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900671 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with the wrong
672 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400673 """
674 context = Context(TLSv1_METHOD)
675 self.assertRaises(TypeError, context.set_timeout)
676 self.assertRaises(TypeError, context.set_timeout, None)
677 self.assertRaises(TypeError, context.set_timeout, 1, None)
678
679
680 def test_get_timeout_wrong_args(self):
681 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900682 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400683 """
684 context = Context(TLSv1_METHOD)
685 self.assertRaises(TypeError, context.get_timeout, None)
686
687
688 def test_timeout(self):
689 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900690 :py:obj:`Context.set_timeout` sets the session timeout for all connections
691 created using the context object. :py:obj:`Context.get_timeout` retrieves this
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400692 value.
693 """
694 context = Context(TLSv1_METHOD)
695 context.set_timeout(1234)
696 self.assertEquals(context.get_timeout(), 1234)
697
698
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500699 if not PY3:
700 def test_timeout_long(self):
701 """
702 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
703 `long` as well as int.
704 """
705 context = Context(TLSv1_METHOD)
706 context.set_timeout(long(1234))
707 self.assertEquals(context.get_timeout(), 1234)
708
709
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400710 def test_set_verify_depth_wrong_args(self):
711 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900712 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called with the wrong
713 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400714 """
715 context = Context(TLSv1_METHOD)
716 self.assertRaises(TypeError, context.set_verify_depth)
717 self.assertRaises(TypeError, context.set_verify_depth, None)
718 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
719
720
721 def test_get_verify_depth_wrong_args(self):
722 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900723 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400724 """
725 context = Context(TLSv1_METHOD)
726 self.assertRaises(TypeError, context.get_verify_depth, None)
727
728
729 def test_verify_depth(self):
730 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900731 :py:obj:`Context.set_verify_depth` sets the number of certificates in a chain
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400732 to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900733 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400734 """
735 context = Context(TLSv1_METHOD)
736 context.set_verify_depth(11)
737 self.assertEquals(context.get_verify_depth(), 11)
738
739
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500740 if not PY3:
741 def test_verify_depth_long(self):
742 """
743 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
744 type `long` as well as int.
745 """
746 context = Context(TLSv1_METHOD)
747 context.set_verify_depth(long(11))
748 self.assertEquals(context.get_verify_depth(), 11)
749
750
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400751 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400752 """
753 Write a new private key out to a new file, encrypted using the given
754 passphrase. Return the path to the new file.
755 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400756 key = PKey()
757 key.generate_key(TYPE_RSA, 128)
758 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400759 fObj = open(pemFile, 'w')
760 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
761 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400762 fObj.close()
763 return pemFile
764
765
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400766 def test_set_passwd_cb_wrong_args(self):
767 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900768 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called with the
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400769 wrong arguments or with a non-callable first argument.
770 """
771 context = Context(TLSv1_METHOD)
772 self.assertRaises(TypeError, context.set_passwd_cb)
773 self.assertRaises(TypeError, context.set_passwd_cb, None)
774 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
775
776
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400777 def test_set_passwd_cb(self):
778 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900779 :py:obj:`Context.set_passwd_cb` accepts a callable which will be invoked when
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400780 a private key is loaded from an encrypted PEM.
781 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400782 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400783 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400784 calledWith = []
785 def passphraseCallback(maxlen, verify, extra):
786 calledWith.append((maxlen, verify, extra))
787 return passphrase
788 context = Context(TLSv1_METHOD)
789 context.set_passwd_cb(passphraseCallback)
790 context.use_privatekey_file(pemFile)
791 self.assertTrue(len(calledWith), 1)
792 self.assertTrue(isinstance(calledWith[0][0], int))
793 self.assertTrue(isinstance(calledWith[0][1], int))
794 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400795
796
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400797 def test_passwd_callback_exception(self):
798 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900799 :py:obj:`Context.use_privatekey_file` propagates any exception raised by the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400800 passphrase callback.
801 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400802 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400803 def passphraseCallback(maxlen, verify, extra):
804 raise RuntimeError("Sorry, I am a fail.")
805
806 context = Context(TLSv1_METHOD)
807 context.set_passwd_cb(passphraseCallback)
808 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
809
810
811 def test_passwd_callback_false(self):
812 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900813 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400814 passphrase callback returns a false value.
815 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400816 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400817 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500818 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400819
820 context = Context(TLSv1_METHOD)
821 context.set_passwd_cb(passphraseCallback)
822 self.assertRaises(Error, context.use_privatekey_file, pemFile)
823
824
825 def test_passwd_callback_non_string(self):
826 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900827 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400828 passphrase callback returns a true non-string value.
829 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400830 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400831 def passphraseCallback(maxlen, verify, extra):
832 return 10
833
834 context = Context(TLSv1_METHOD)
835 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800836 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400837
838
839 def test_passwd_callback_too_long(self):
840 """
841 If the passphrase returned by the passphrase callback returns a string
842 longer than the indicated maximum length, it is truncated.
843 """
844 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400845 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400846 pemFile = self._write_encrypted_pem(passphrase)
847 def passphraseCallback(maxlen, verify, extra):
848 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400849 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400850
851 context = Context(TLSv1_METHOD)
852 context.set_passwd_cb(passphraseCallback)
853 # This shall succeed because the truncated result is the correct
854 # passphrase.
855 context.use_privatekey_file(pemFile)
856
857
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400858 def test_set_info_callback(self):
859 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900860 :py:obj:`Context.set_info_callback` accepts a callable which will be invoked
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400861 when certain information about an SSL connection is available.
862 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500863 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400864
865 clientSSL = Connection(Context(TLSv1_METHOD), client)
866 clientSSL.set_connect_state()
867
868 called = []
869 def info(conn, where, ret):
870 called.append((conn, where, ret))
871 context = Context(TLSv1_METHOD)
872 context.set_info_callback(info)
873 context.use_certificate(
874 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
875 context.use_privatekey(
876 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
877
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400878 serverSSL = Connection(context, server)
879 serverSSL.set_accept_state()
880
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500881 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400882
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500883 # The callback must always be called with a Connection instance as the
884 # first argument. It would probably be better to split this into
885 # separate tests for client and server side info callbacks so we could
886 # assert it is called with the right Connection instance. It would
887 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500888 notConnections = [
889 conn for (conn, where, ret) in called
890 if not isinstance(conn, Connection)]
891 self.assertEqual(
892 [], notConnections,
893 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400894
895
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400896 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400897 """
898 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400899 its :py:obj:`load_verify_locations` method with the given arguments.
900 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400901 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500902 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400903
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400904 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400905 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400906 # Require that the server certificate verify properly or the
907 # connection will fail.
908 clientContext.set_verify(
909 VERIFY_PEER,
910 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
911
912 clientSSL = Connection(clientContext, client)
913 clientSSL.set_connect_state()
914
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400915 serverContext = Context(TLSv1_METHOD)
916 serverContext.use_certificate(
917 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
918 serverContext.use_privatekey(
919 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
920
921 serverSSL = Connection(serverContext, server)
922 serverSSL.set_accept_state()
923
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400924 # Without load_verify_locations above, the handshake
925 # will fail:
926 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
927 # 'certificate verify failed')]
928 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400929
930 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400931 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400932
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500933
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400934 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400935 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400936 Verify that if path to a file containing a certificate is passed to
937 ``Context.load_verify_locations`` for the ``cafile`` parameter, that
938 certificate is used as a trust root for the purposes of verifying
939 connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400940 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400941 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400942 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400943 fObj.close()
944
945 self._load_verify_locations_test(cafile)
946
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400947
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400948 def test_load_verify_bytes_cafile(self):
949 """
950 :py:obj:`Context.load_verify_locations` accepts a file name as a
951 ``bytes`` instance and uses the certificates within for verification
952 purposes.
953 """
954 cafile = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
955 self._load_verify_cafile(cafile)
956
957
958 def test_load_verify_unicode_cafile(self):
959 """
960 :py:obj:`Context.load_verify_locations` accepts a file name as a
961 ``unicode`` instance and uses the certificates within for verification
962 purposes.
963 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -0400964 self._load_verify_cafile(
965 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
966 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400967
968
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400969 def test_load_verify_invalid_file(self):
970 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900971 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when passed a
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400972 non-existent cafile.
973 """
974 clientContext = Context(TLSv1_METHOD)
975 self.assertRaises(
976 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400977
978
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400979 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400980 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400981 Verify that if path to a directory containing certificate files is
982 passed to ``Context.load_verify_locations`` for the ``capath``
983 parameter, those certificates are used as trust roots for the purposes
984 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400985 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400986 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400987 # Hash values computed manually with c_rehash to avoid depending on
988 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
989 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500990 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400991 cafile = join_bytes_or_unicode(capath, name)
992 with open(cafile, 'w') as fObj:
993 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400994
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400995 self._load_verify_locations_test(None, capath)
996
997
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400998 def test_load_verify_directory_bytes_capath(self):
999 """
1000 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1001 ``bytes`` instance and uses the certificates within for verification
1002 purposes.
1003 """
1004 self._load_verify_directory_locations_capath(
1005 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
1006 )
1007
1008
1009 def test_load_verify_directory_unicode_capath(self):
1010 """
1011 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1012 ``unicode`` instance and uses the certificates within for verification
1013 purposes.
1014 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001015 self._load_verify_directory_locations_capath(
1016 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
1017 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001018
1019
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001020 def test_load_verify_locations_wrong_args(self):
1021 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001022 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if called with
1023 the wrong number of arguments or with non-:py:obj:`str` arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001024 """
1025 context = Context(TLSv1_METHOD)
1026 self.assertRaises(TypeError, context.load_verify_locations)
1027 self.assertRaises(TypeError, context.load_verify_locations, object())
1028 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
1029 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
1030
1031
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001032 if platform == "win32":
1033 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001034 "See LP#404343 and LP#404344."
1035 else:
1036 def test_set_default_verify_paths(self):
1037 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001038 :py:obj:`Context.set_default_verify_paths` causes the platform-specific CA
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001039 certificate locations to be used for verification purposes.
1040 """
1041 # Testing this requires a server with a certificate signed by one of
1042 # the CAs in the platform CA location. Getting one of those costs
1043 # money. Fortunately (or unfortunately, depending on your
1044 # perspective), it's easy to think of a public server on the
1045 # internet which has such a certificate. Connecting to the network
1046 # in a unit test is bad, but it's the only way I can think of to
1047 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001048
Alex Gaynorb586da32014-11-15 09:22:21 -08001049 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
1050 context = Context(TLSv1_METHOD)
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001051 context.set_default_verify_paths()
1052 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02001053 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001054 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001055
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001056 client = socket()
1057 client.connect(('verisign.com', 443))
1058 clientSSL = Connection(context, client)
1059 clientSSL.set_connect_state()
1060 clientSSL.do_handshake()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001061 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001062 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001063
1064
1065 def test_set_default_verify_paths_signature(self):
1066 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001067 :py:obj:`Context.set_default_verify_paths` takes no arguments and raises
1068 :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001069 """
1070 context = Context(TLSv1_METHOD)
1071 self.assertRaises(TypeError, context.set_default_verify_paths, None)
1072 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
1073 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001074
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001075
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001076 def test_add_extra_chain_cert_invalid_cert(self):
1077 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001078 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if called with
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001079 other than one argument or if called with an object which is not an
Jonathan Ballet648875f2011-07-16 14:14:58 +09001080 instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001081 """
1082 context = Context(TLSv1_METHOD)
1083 self.assertRaises(TypeError, context.add_extra_chain_cert)
1084 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
1085 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
1086
1087
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001088 def _handshake_test(self, serverContext, clientContext):
1089 """
1090 Verify that a client and server created with the given contexts can
1091 successfully handshake and communicate.
1092 """
1093 serverSocket, clientSocket = socket_pair()
1094
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001095 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001096 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001097
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001098 client = Connection(clientContext, clientSocket)
1099 client.set_connect_state()
1100
1101 # Make them talk to each other.
1102 # self._interactInMemory(client, server)
1103 for i in range(3):
1104 for s in [client, server]:
1105 try:
1106 s.do_handshake()
1107 except WantReadError:
1108 pass
1109
1110
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001111 def test_set_verify_callback_connection_argument(self):
1112 """
1113 The first argument passed to the verify callback is the
1114 :py:class:`Connection` instance for which verification is taking place.
1115 """
1116 serverContext = Context(TLSv1_METHOD)
1117 serverContext.use_privatekey(
1118 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1119 serverContext.use_certificate(
1120 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1121 serverConnection = Connection(serverContext, None)
1122
1123 class VerifyCallback(object):
1124 def callback(self, connection, *args):
1125 self.connection = connection
1126 return 1
1127
1128 verify = VerifyCallback()
1129 clientContext = Context(TLSv1_METHOD)
1130 clientContext.set_verify(VERIFY_PEER, verify.callback)
1131 clientConnection = Connection(clientContext, None)
1132 clientConnection.set_connect_state()
1133
1134 self._handshakeInMemory(clientConnection, serverConnection)
1135
1136 self.assertIdentical(verify.connection, clientConnection)
1137
1138
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001139 def test_set_verify_callback_exception(self):
1140 """
1141 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1142 exception, verification fails and the exception is propagated to the
1143 caller of :py:obj:`Connection.do_handshake`.
1144 """
1145 serverContext = Context(TLSv1_METHOD)
1146 serverContext.use_privatekey(
1147 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1148 serverContext.use_certificate(
1149 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1150
1151 clientContext = Context(TLSv1_METHOD)
1152 def verify_callback(*args):
1153 raise Exception("silly verify failure")
1154 clientContext.set_verify(VERIFY_PEER, verify_callback)
1155
1156 exc = self.assertRaises(
1157 Exception, self._handshake_test, serverContext, clientContext)
1158 self.assertEqual("silly verify failure", str(exc))
1159
1160
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001161 def test_add_extra_chain_cert(self):
1162 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001163 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509` instance to add to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001164 the certificate chain.
1165
Jonathan Ballet648875f2011-07-16 14:14:58 +09001166 See :py:obj:`_create_certificate_chain` for the details of the certificate
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001167 chain tested.
1168
1169 The chain is tested by starting a server with scert and connecting
1170 to it with a client which trusts cacert and requires verification to
1171 succeed.
1172 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001173 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001174 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1175
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001176 # Dump the CA certificate to a file because that's the only way to load
1177 # it as a trusted CA in the client context.
1178 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001179 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001180 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001181 fObj.close()
1182
1183 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001184 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001185 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001186 fObj.close()
1187
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001188 # Create the server context
1189 serverContext = Context(TLSv1_METHOD)
1190 serverContext.use_privatekey(skey)
1191 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001192 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001193 serverContext.add_extra_chain_cert(icert)
1194
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001195 # Create the client
1196 clientContext = Context(TLSv1_METHOD)
1197 clientContext.set_verify(
1198 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001199 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001200
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001201 # Try it out.
1202 self._handshake_test(serverContext, clientContext)
1203
1204
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001205 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001206 """
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001207 Verify that :py:obj:`Context.use_certificate_chain_file` reads a
1208 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001209
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001210 The chain is tested by starting a server with scert and connecting to
1211 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001212 succeed.
1213 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001214 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001215 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1216
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001217 makedirs(certdir)
1218
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001219 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1220 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001221
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001222 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001223 with open(chainFile, 'wb') as fObj:
1224 # Most specific to least general.
1225 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1226 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1227 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1228
1229 with open(caFile, 'w') as fObj:
1230 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001231
1232 serverContext = Context(TLSv1_METHOD)
1233 serverContext.use_certificate_chain_file(chainFile)
1234 serverContext.use_privatekey(skey)
1235
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001236 clientContext = Context(TLSv1_METHOD)
1237 clientContext.set_verify(
1238 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001239 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001240
1241 self._handshake_test(serverContext, clientContext)
1242
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001243
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001244 def test_use_certificate_chain_file_bytes(self):
1245 """
1246 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1247 an instance of ``bytes``) to specify additional certificates to use to
1248 construct and verify a trust chain.
1249 """
1250 self._use_certificate_chain_file_test(
1251 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
1252 )
1253
1254
1255 def test_use_certificate_chain_file_unicode(self):
1256 """
1257 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1258 an instance of ``unicode``) to specify additional certificates to use
1259 to construct and verify a trust chain.
1260 """
1261 self._use_certificate_chain_file_test(
1262 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
1263 )
1264
1265
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001266 def test_use_certificate_chain_file_wrong_args(self):
1267 """
1268 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1269 if passed zero or more than one argument or when passed a non-byte
1270 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error` when
1271 passed a bad chain file name (for example, the name of a file which does
1272 not exist).
1273 """
1274 context = Context(TLSv1_METHOD)
1275 self.assertRaises(TypeError, context.use_certificate_chain_file)
1276 self.assertRaises(TypeError, context.use_certificate_chain_file, object())
1277 self.assertRaises(TypeError, context.use_certificate_chain_file, b"foo", object())
1278
1279 self.assertRaises(Error, context.use_certificate_chain_file, self.mktemp())
1280
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001281 # XXX load_client_ca
1282 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001283
1284 def test_get_verify_mode_wrong_args(self):
1285 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001286 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001287 arguments.
1288 """
1289 context = Context(TLSv1_METHOD)
1290 self.assertRaises(TypeError, context.get_verify_mode, None)
1291
1292
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001293 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001294 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001295 :py:obj:`Context.get_verify_mode` returns the verify mode flags previously
1296 passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001297 """
1298 context = Context(TLSv1_METHOD)
1299 self.assertEquals(context.get_verify_mode(), 0)
1300 context.set_verify(
1301 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1302 self.assertEquals(
1303 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1304
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001305
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001306 if not PY3:
1307 def test_set_verify_mode_long(self):
1308 """
1309 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1310 type :py:obj:`long` as well as :py:obj:`int`.
1311 """
1312 context = Context(TLSv1_METHOD)
1313 self.assertEquals(context.get_verify_mode(), 0)
1314 context.set_verify(
1315 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None)
1316 self.assertEquals(
1317 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1318
1319
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001320 def test_load_tmp_dh_wrong_args(self):
1321 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001322 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
1323 number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001324 """
1325 context = Context(TLSv1_METHOD)
1326 self.assertRaises(TypeError, context.load_tmp_dh)
1327 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1328 self.assertRaises(TypeError, context.load_tmp_dh, object())
1329
1330
1331 def test_load_tmp_dh_missing_file(self):
1332 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001333 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the specified file
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001334 does not exist.
1335 """
1336 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001337 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001338
1339
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001340 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001341 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001342 with open(dhfilename, "w") as dhfile:
1343 dhfile.write(dhparam)
1344
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001345 context.load_tmp_dh(dhfilename)
1346 # XXX What should I assert here? -exarkun
1347
1348
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001349 def test_load_tmp_dh_bytes(self):
1350 """
1351 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1352 specified file (given as ``bytes``).
1353 """
1354 self._load_tmp_dh_test(
1355 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
1356 )
1357
1358
1359 def test_load_tmp_dh_unicode(self):
1360 """
1361 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1362 specified file (given as ``unicode``).
1363 """
1364 self._load_tmp_dh_test(
1365 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
1366 )
1367
1368
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001369 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001370 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001371 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001372 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001373 """
1374 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001375 for curve in get_elliptic_curves():
1376 # The only easily "assertable" thing is that it does not raise an
1377 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001378 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001379
1380
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001381 def test_set_cipher_list_bytes(self):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001382 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001383 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
1384 ciphers which connections created with the context object will be able
1385 to choose from.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001386 """
1387 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001388 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001389 conn = Connection(context, None)
1390 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001391
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001392
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001393 def test_set_cipher_list_text(self):
1394 """
1395 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
1396 the ciphers which connections created with the context object will be
1397 able to choose from.
1398 """
1399 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -05001400 context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001401 conn = Connection(context, None)
1402 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
1403
1404
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001405 def test_set_cipher_list_wrong_args(self):
1406 """
Jean-Paul Calderone17044832014-01-18 10:20:11 -05001407 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
1408 passed zero arguments or more than one argument or when passed a
1409 non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001410 passed an incorrect cipher list string.
1411 """
1412 context = Context(TLSv1_METHOD)
1413 self.assertRaises(TypeError, context.set_cipher_list)
1414 self.assertRaises(TypeError, context.set_cipher_list, object())
1415 self.assertRaises(TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object())
1416
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001417 self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001418
1419
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001420 def test_set_session_cache_mode_wrong_args(self):
1421 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001422 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1423 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001424 """
1425 context = Context(TLSv1_METHOD)
1426 self.assertRaises(TypeError, context.set_session_cache_mode)
1427 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1428
1429
1430 def test_get_session_cache_mode_wrong_args(self):
1431 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001432 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1433 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001434 """
1435 context = Context(TLSv1_METHOD)
1436 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1437
1438
1439 def test_session_cache_mode(self):
1440 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001441 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1442 cached. The setting can be retrieved via
1443 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001444 """
1445 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001446 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001447 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1448 self.assertEqual(SESS_CACHE_OFF, off)
1449 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1450
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001451 if not PY3:
1452 def test_session_cache_mode_long(self):
1453 """
1454 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1455 of type :py:obj:`long` as well as :py:obj:`int`.
1456 """
1457 context = Context(TLSv1_METHOD)
1458 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1459 self.assertEqual(
1460 SESS_CACHE_BOTH, context.get_session_cache_mode())
1461
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001462
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001463 def test_get_cert_store(self):
1464 """
1465 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store` instance.
1466 """
1467 context = Context(TLSv1_METHOD)
1468 store = context.get_cert_store()
1469 self.assertIsInstance(store, X509Store)
1470
1471
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001472
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001473class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1474 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001475 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
1476 :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001477 """
1478 def test_wrong_args(self):
1479 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001480 :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001481 with other than one argument.
1482 """
1483 context = Context(TLSv1_METHOD)
1484 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1485 self.assertRaises(
1486 TypeError, context.set_tlsext_servername_callback, 1, 2)
1487
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001488
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001489 def test_old_callback_forgotten(self):
1490 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001491 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001492 callback, the one it replaces is dereferenced.
1493 """
1494 def callback(connection):
1495 pass
1496
1497 def replacement(connection):
1498 pass
1499
1500 context = Context(TLSv1_METHOD)
1501 context.set_tlsext_servername_callback(callback)
1502
1503 tracker = ref(callback)
1504 del callback
1505
1506 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001507
1508 # One run of the garbage collector happens to work on CPython. PyPy
1509 # doesn't collect the underlying object until a second run for whatever
1510 # reason. That's fine, it still demonstrates our code has properly
1511 # dropped the reference.
1512 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001513 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001514
1515 callback = tracker()
1516 if callback is not None:
1517 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001518 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001519 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001520
1521
1522 def test_no_servername(self):
1523 """
1524 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001525 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
1526 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001527 """
1528 args = []
1529 def servername(conn):
1530 args.append((conn, conn.get_servername()))
1531 context = Context(TLSv1_METHOD)
1532 context.set_tlsext_servername_callback(servername)
1533
1534 # Lose our reference to it. The Context is responsible for keeping it
1535 # alive now.
1536 del servername
1537 collect()
1538
1539 # Necessary to actually accept the connection
1540 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1541 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1542
1543 # Do a little connection to trigger the logic
1544 server = Connection(context, None)
1545 server.set_accept_state()
1546
1547 client = Connection(Context(TLSv1_METHOD), None)
1548 client.set_connect_state()
1549
1550 self._interactInMemory(server, client)
1551
1552 self.assertEqual([(server, None)], args)
1553
1554
1555 def test_servername(self):
1556 """
1557 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +09001558 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
1559 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001560 """
1561 args = []
1562 def servername(conn):
1563 args.append((conn, conn.get_servername()))
1564 context = Context(TLSv1_METHOD)
1565 context.set_tlsext_servername_callback(servername)
1566
1567 # Necessary to actually accept the connection
1568 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1569 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1570
1571 # Do a little connection to trigger the logic
1572 server = Connection(context, None)
1573 server.set_accept_state()
1574
1575 client = Connection(Context(TLSv1_METHOD), None)
1576 client.set_connect_state()
1577 client.set_tlsext_host_name(b("foo1.example.com"))
1578
1579 self._interactInMemory(server, client)
1580
1581 self.assertEqual([(server, b("foo1.example.com"))], args)
1582
1583
1584
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001585class SessionTests(TestCase):
1586 """
1587 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1588 """
1589 def test_construction(self):
1590 """
1591 :py:class:`Session` can be constructed with no arguments, creating a new
1592 instance of that type.
1593 """
1594 new_session = Session()
1595 self.assertTrue(isinstance(new_session, Session))
1596
1597
1598 def test_construction_wrong_args(self):
1599 """
1600 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
1601 is raised.
1602 """
1603 self.assertRaises(TypeError, Session, 123)
1604 self.assertRaises(TypeError, Session, "hello")
1605 self.assertRaises(TypeError, Session, object())
1606
1607
1608
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001609class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05001610 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001611 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001612 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001613 # XXX get_peer_certificate -> None
1614 # XXX sock_shutdown
1615 # XXX master_key -> TypeError
1616 # XXX server_random -> TypeError
1617 # XXX state_string
1618 # XXX connect -> TypeError
1619 # XXX connect_ex -> TypeError
1620 # XXX set_connect_state -> TypeError
1621 # XXX set_accept_state -> TypeError
1622 # XXX renegotiate_pending
1623 # XXX do_handshake -> TypeError
1624 # XXX bio_read -> TypeError
1625 # XXX recv -> TypeError
1626 # XXX send -> TypeError
1627 # XXX bio_write -> TypeError
1628
Rick Deane15b1472009-07-09 15:53:42 -05001629 def test_type(self):
1630 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001631 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001632 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05001633 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001634 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05001635 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001636 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05001637
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001638
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001639 def test_get_context(self):
1640 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001641 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
1642 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001643 """
1644 context = Context(TLSv1_METHOD)
1645 connection = Connection(context, None)
1646 self.assertIdentical(connection.get_context(), context)
1647
1648
1649 def test_get_context_wrong_args(self):
1650 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001651 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001652 arguments.
1653 """
1654 connection = Connection(Context(TLSv1_METHOD), None)
1655 self.assertRaises(TypeError, connection.get_context, None)
1656
1657
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001658 def test_set_context_wrong_args(self):
1659 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001660 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
1661 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001662 than 1.
1663 """
1664 ctx = Context(TLSv1_METHOD)
1665 connection = Connection(ctx, None)
1666 self.assertRaises(TypeError, connection.set_context)
1667 self.assertRaises(TypeError, connection.set_context, object())
1668 self.assertRaises(TypeError, connection.set_context, "hello")
1669 self.assertRaises(TypeError, connection.set_context, 1)
1670 self.assertRaises(TypeError, connection.set_context, 1, 2)
1671 self.assertRaises(
1672 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
1673 self.assertIdentical(ctx, connection.get_context())
1674
1675
1676 def test_set_context(self):
1677 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001678 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001679 for the connection.
1680 """
1681 original = Context(SSLv23_METHOD)
1682 replacement = Context(TLSv1_METHOD)
1683 connection = Connection(original, None)
1684 connection.set_context(replacement)
1685 self.assertIdentical(replacement, connection.get_context())
1686 # Lose our references to the contexts, just in case the Connection isn't
1687 # properly managing its own contributions to their reference counts.
1688 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001689 collect()
1690
1691
1692 def test_set_tlsext_host_name_wrong_args(self):
1693 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001694 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001695 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09001696 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001697 """
1698 conn = Connection(Context(TLSv1_METHOD), None)
1699 self.assertRaises(TypeError, conn.set_tlsext_host_name)
1700 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
1701 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
1702 self.assertRaises(
1703 TypeError, conn.set_tlsext_host_name, b("with\0null"))
1704
1705 if version_info >= (3,):
1706 # On Python 3.x, don't accidentally implicitly convert from text.
1707 self.assertRaises(
1708 TypeError,
1709 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001710
1711
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001712 def test_get_servername_wrong_args(self):
1713 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001714 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001715 arguments.
1716 """
1717 connection = Connection(Context(TLSv1_METHOD), None)
1718 self.assertRaises(TypeError, connection.get_servername, object())
1719 self.assertRaises(TypeError, connection.get_servername, 1)
1720 self.assertRaises(TypeError, connection.get_servername, "hello")
1721
1722
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001723 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001724 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001725 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001726 immediate read.
1727 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001728 connection = Connection(Context(TLSv1_METHOD), None)
1729 self.assertEquals(connection.pending(), 0)
1730
1731
1732 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001733 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001734 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001735 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001736 connection = Connection(Context(TLSv1_METHOD), None)
1737 self.assertRaises(TypeError, connection.pending, None)
1738
1739
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001740 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001741 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001742 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001743 argument or with the wrong number of arguments.
1744 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001745 connection = Connection(Context(TLSv1_METHOD), socket())
1746 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001747 self.assertRaises(TypeError, connection.connect)
1748 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001749
1750
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001751 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001752 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001753 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001754 connect method raises it.
1755 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001756 client = socket()
1757 context = Context(TLSv1_METHOD)
1758 clientSSL = Connection(context, client)
1759 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04001760 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001761
1762
1763 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001764 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001765 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001766 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001767 port = socket()
1768 port.bind(('', 0))
1769 port.listen(3)
1770
1771 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001772 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
1773 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001774
1775
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001776 if platform == "darwin":
1777 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
1778 else:
1779 def test_connect_ex(self):
1780 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001781 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001782 errno instead of raising an exception.
1783 """
1784 port = socket()
1785 port.bind(('', 0))
1786 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001787
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001788 clientSSL = Connection(Context(TLSv1_METHOD), socket())
1789 clientSSL.setblocking(False)
1790 result = clientSSL.connect_ex(port.getsockname())
1791 expected = (EINPROGRESS, EWOULDBLOCK)
1792 self.assertTrue(
1793 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001794
1795
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001796 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001797 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001798 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001799 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001800 connection = Connection(Context(TLSv1_METHOD), socket())
1801 self.assertRaises(TypeError, connection.accept, None)
1802
1803
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001804 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001805 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001806 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
1807 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001808 connection originated from.
1809 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001810 ctx = Context(TLSv1_METHOD)
1811 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1812 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001813 port = socket()
1814 portSSL = Connection(ctx, port)
1815 portSSL.bind(('', 0))
1816 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001817
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001818 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001819
1820 # Calling portSSL.getsockname() here to get the server IP address sounds
1821 # great, but frequently fails on Windows.
1822 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001823
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001824 serverSSL, address = portSSL.accept()
1825
1826 self.assertTrue(isinstance(serverSSL, Connection))
1827 self.assertIdentical(serverSSL.get_context(), ctx)
1828 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001829
1830
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001831 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001832 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001833 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001834 number of arguments or with arguments other than integers.
1835 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001836 connection = Connection(Context(TLSv1_METHOD), None)
1837 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04001838 self.assertRaises(TypeError, connection.get_shutdown, None)
1839 self.assertRaises(TypeError, connection.set_shutdown)
1840 self.assertRaises(TypeError, connection.set_shutdown, None)
1841 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001842
1843
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001844 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001845 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001846 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001847 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001848 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001849 self.assertFalse(server.shutdown())
1850 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001851 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001852 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
1853 client.shutdown()
1854 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
1855 self.assertRaises(ZeroReturnError, server.recv, 1024)
1856 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001857
1858
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001859 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001860 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001861 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001862 process.
1863 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001864 connection = Connection(Context(TLSv1_METHOD), socket())
1865 connection.set_shutdown(RECEIVED_SHUTDOWN)
1866 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1867
1868
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05001869 if not PY3:
1870 def test_set_shutdown_long(self):
1871 """
1872 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
1873 of type :py:obj:`long` as well as :py:obj:`int`.
1874 """
1875 connection = Connection(Context(TLSv1_METHOD), socket())
1876 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
1877 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1878
1879
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001880 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001881 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001882 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
1883 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001884 with any arguments.
1885 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001886 conn = Connection(Context(TLSv1_METHOD), None)
1887 self.assertRaises(TypeError, conn.get_app_data, None)
1888 self.assertRaises(TypeError, conn.set_app_data)
1889 self.assertRaises(TypeError, conn.set_app_data, None, None)
1890
1891
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001892 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001893 """
1894 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001895 :py:obj:`Connection.set_app_data` and later retrieved with
1896 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001897 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001898 conn = Connection(Context(TLSv1_METHOD), None)
1899 app_data = object()
1900 conn.set_app_data(app_data)
1901 self.assertIdentical(conn.get_app_data(), app_data)
1902
1903
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001904 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001905 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001906 :py:obj:`Connection.makefile` is not implemented and calling that method raises
1907 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001908 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001909 conn = Connection(Context(TLSv1_METHOD), None)
1910 self.assertRaises(NotImplementedError, conn.makefile)
1911
1912
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001913 def test_get_peer_cert_chain_wrong_args(self):
1914 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001915 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001916 arguments.
1917 """
1918 conn = Connection(Context(TLSv1_METHOD), None)
1919 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
1920 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
1921 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
1922 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
1923
1924
1925 def test_get_peer_cert_chain(self):
1926 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001927 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001928 the connected server returned for the certification verification.
1929 """
1930 chain = _create_certificate_chain()
1931 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1932
1933 serverContext = Context(TLSv1_METHOD)
1934 serverContext.use_privatekey(skey)
1935 serverContext.use_certificate(scert)
1936 serverContext.add_extra_chain_cert(icert)
1937 serverContext.add_extra_chain_cert(cacert)
1938 server = Connection(serverContext, None)
1939 server.set_accept_state()
1940
1941 # Create the client
1942 clientContext = Context(TLSv1_METHOD)
1943 clientContext.set_verify(VERIFY_NONE, verify_cb)
1944 client = Connection(clientContext, None)
1945 client.set_connect_state()
1946
1947 self._interactInMemory(client, server)
1948
1949 chain = client.get_peer_cert_chain()
1950 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001951 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001952 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001953 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001954 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001955 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001956 "Authority Certificate", chain[2].get_subject().CN)
1957
1958
1959 def test_get_peer_cert_chain_none(self):
1960 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001961 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001962 certificate chain.
1963 """
1964 ctx = Context(TLSv1_METHOD)
1965 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1966 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1967 server = Connection(ctx, None)
1968 server.set_accept_state()
1969 client = Connection(Context(TLSv1_METHOD), None)
1970 client.set_connect_state()
1971 self._interactInMemory(client, server)
1972 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001973
1974
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001975 def test_get_session_wrong_args(self):
1976 """
1977 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
1978 with any arguments.
1979 """
1980 ctx = Context(TLSv1_METHOD)
1981 server = Connection(ctx, None)
1982 self.assertRaises(TypeError, server.get_session, 123)
1983 self.assertRaises(TypeError, server.get_session, "hello")
1984 self.assertRaises(TypeError, server.get_session, object())
1985
1986
1987 def test_get_session_unconnected(self):
1988 """
1989 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
1990 an object which has not been connected.
1991 """
1992 ctx = Context(TLSv1_METHOD)
1993 server = Connection(ctx, None)
1994 session = server.get_session()
1995 self.assertIdentical(None, session)
1996
1997
1998 def test_server_get_session(self):
1999 """
2000 On the server side of a connection, :py:obj:`Connection.get_session`
2001 returns a :py:class:`Session` instance representing the SSL session for
2002 that connection.
2003 """
2004 server, client = self._loopback()
2005 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002006 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002007
2008
2009 def test_client_get_session(self):
2010 """
2011 On the client side of a connection, :py:obj:`Connection.get_session`
2012 returns a :py:class:`Session` instance representing the SSL session for
2013 that connection.
2014 """
2015 server, client = self._loopback()
2016 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002017 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002018
2019
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002020 def test_set_session_wrong_args(self):
2021 """
2022 If called with an object that is not an instance of :py:class:`Session`,
2023 or with other than one argument, :py:obj:`Connection.set_session` raises
2024 :py:obj:`TypeError`.
2025 """
2026 ctx = Context(TLSv1_METHOD)
2027 connection = Connection(ctx, None)
2028 self.assertRaises(TypeError, connection.set_session)
2029 self.assertRaises(TypeError, connection.set_session, 123)
2030 self.assertRaises(TypeError, connection.set_session, "hello")
2031 self.assertRaises(TypeError, connection.set_session, object())
2032 self.assertRaises(
2033 TypeError, connection.set_session, Session(), Session())
2034
2035
2036 def test_client_set_session(self):
2037 """
2038 :py:obj:`Connection.set_session`, when used prior to a connection being
2039 established, accepts a :py:class:`Session` instance and causes an
2040 attempt to re-use the session it represents when the SSL handshake is
2041 performed.
2042 """
2043 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2044 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2045 ctx = Context(TLSv1_METHOD)
2046 ctx.use_privatekey(key)
2047 ctx.use_certificate(cert)
2048 ctx.set_session_id("unity-test")
2049
2050 def makeServer(socket):
2051 server = Connection(ctx, socket)
2052 server.set_accept_state()
2053 return server
2054
2055 originalServer, originalClient = self._loopback(
2056 serverFactory=makeServer)
2057 originalSession = originalClient.get_session()
2058
2059 def makeClient(socket):
2060 client = self._loopbackClientFactory(socket)
2061 client.set_session(originalSession)
2062 return client
2063 resumedServer, resumedClient = self._loopback(
2064 serverFactory=makeServer,
2065 clientFactory=makeClient)
2066
2067 # This is a proxy: in general, we have no access to any unique
2068 # identifier for the session (new enough versions of OpenSSL expose a
2069 # hash which could be usable, but "new enough" is very, very new).
2070 # Instead, exploit the fact that the master key is re-used if the
2071 # session is re-used. As long as the master key for the two connections
2072 # is the same, the session was re-used!
2073 self.assertEqual(
2074 originalServer.master_key(), resumedServer.master_key())
2075
2076
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002077 def test_set_session_wrong_method(self):
2078 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002079 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
2080 instance associated with a context using a different SSL method than the
2081 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
2082 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002083 """
2084 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2085 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2086 ctx = Context(TLSv1_METHOD)
2087 ctx.use_privatekey(key)
2088 ctx.use_certificate(cert)
2089 ctx.set_session_id("unity-test")
2090
2091 def makeServer(socket):
2092 server = Connection(ctx, socket)
2093 server.set_accept_state()
2094 return server
2095
2096 originalServer, originalClient = self._loopback(
2097 serverFactory=makeServer)
2098 originalSession = originalClient.get_session()
2099
2100 def makeClient(socket):
2101 # Intentionally use a different, incompatible method here.
2102 client = Connection(Context(SSLv3_METHOD), socket)
2103 client.set_connect_state()
2104 client.set_session(originalSession)
2105 return client
2106
2107 self.assertRaises(
2108 Error,
2109 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2110
2111
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002112 def test_wantWriteError(self):
2113 """
2114 :py:obj:`Connection` methods which generate output raise
2115 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2116 fail indicating a should-write state.
2117 """
2118 client_socket, server_socket = socket_pair()
2119 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002120 # anything. Only write a single byte at a time so we can be sure we
2121 # completely fill the buffer. Even though the socket API is allowed to
2122 # signal a short write via its return value it seems this doesn't
2123 # always happen on all platforms (FreeBSD and OS X particular) for the
2124 # very last bit of available buffer space.
2125 msg = b"x"
2126 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002127 try:
2128 client_socket.send(msg)
2129 except error as e:
2130 if e.errno == EWOULDBLOCK:
2131 break
2132 raise
2133 else:
2134 self.fail(
2135 "Failed to fill socket buffer, cannot test BIO want write")
2136
2137 ctx = Context(TLSv1_METHOD)
2138 conn = Connection(ctx, client_socket)
2139 # Client's speak first, so make it an SSL client
2140 conn.set_connect_state()
2141 self.assertRaises(WantWriteError, conn.do_handshake)
2142
2143 # XXX want_read
2144
Fedor Brunner416f4a12014-03-28 13:18:38 +01002145 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002146 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002147 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2148 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002149 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002150 ctx = Context(TLSv1_METHOD)
2151 connection = Connection(ctx, None)
2152 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002153
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002154
Fedor Brunner416f4a12014-03-28 13:18:38 +01002155 def test_get_peer_finished_before_connect(self):
2156 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002157 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2158 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002159 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002160 ctx = Context(TLSv1_METHOD)
2161 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002162 self.assertEqual(connection.get_peer_finished(), None)
2163
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002164
Fedor Brunner416f4a12014-03-28 13:18:38 +01002165 def test_get_finished(self):
2166 """
2167 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002168 message send from client, or server. Finished messages are send during
2169 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002170 """
2171
Fedor Brunner5747b932014-03-05 14:22:34 +01002172 server, client = self._loopback()
2173
2174 self.assertNotEqual(server.get_finished(), None)
2175 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002176
Jean-Paul Calderoned979f232014-03-30 11:58:00 -04002177
Fedor Brunner416f4a12014-03-28 13:18:38 +01002178 def test_get_peer_finished(self):
2179 """
2180 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002181 message received from client, or server. Finished messages are send
2182 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002183 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002184 server, client = self._loopback()
2185
2186 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002187 self.assertTrue(len(server.get_peer_finished()) > 0)
2188
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002189
Fedor Brunner416f4a12014-03-28 13:18:38 +01002190 def test_tls_finished_message_symmetry(self):
2191 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002192 The TLS Finished message send by server must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002193 received by client.
2194
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002195 The TLS Finished message send by client must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002196 received by server.
2197 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002198 server, client = self._loopback()
2199
Fedor Brunner5747b932014-03-05 14:22:34 +01002200 self.assertEqual(server.get_finished(), client.get_peer_finished())
2201 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002202
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002203
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002204 def test_get_cipher_name_before_connect(self):
2205 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002206 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2207 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002208 """
2209 ctx = Context(TLSv1_METHOD)
2210 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002211 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002212
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002213
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002214 def test_get_cipher_name(self):
2215 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002216 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2217 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002218 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002219 server, client = self._loopback()
2220 server_cipher_name, client_cipher_name = \
2221 server.get_cipher_name(), client.get_cipher_name()
2222
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002223 self.assertIsInstance(server_cipher_name, text_type)
2224 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002225
2226 self.assertEqual(server_cipher_name, client_cipher_name)
2227
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002228
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002229 def test_get_cipher_version_before_connect(self):
2230 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002231 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2232 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002233 """
2234 ctx = Context(TLSv1_METHOD)
2235 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002236 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002237
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002238
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002239 def test_get_cipher_version(self):
2240 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002241 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2242 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002243 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002244 server, client = self._loopback()
2245 server_cipher_version, client_cipher_version = \
2246 server.get_cipher_version(), client.get_cipher_version()
2247
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002248 self.assertIsInstance(server_cipher_version, text_type)
2249 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002250
2251 self.assertEqual(server_cipher_version, client_cipher_version)
2252
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002253
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002254 def test_get_cipher_bits_before_connect(self):
2255 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002256 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2257 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002258 """
2259 ctx = Context(TLSv1_METHOD)
2260 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002261 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002262
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002263
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002264 def test_get_cipher_bits(self):
2265 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002266 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2267 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002268 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002269 server, client = self._loopback()
2270 server_cipher_bits, client_cipher_bits = \
2271 server.get_cipher_bits(), client.get_cipher_bits()
2272
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002273 self.assertIsInstance(server_cipher_bits, int)
2274 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002275
2276 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002277
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002278
2279
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002280class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002281 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002282 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002283 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002284 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002285 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002286 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002287 arguments.
2288 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002289 connection = Connection(Context(TLSv1_METHOD), None)
2290 self.assertRaises(TypeError, connection.get_cipher_list, None)
2291
2292
2293 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002294 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002295 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2296 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002297 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002298 connection = Connection(Context(TLSv1_METHOD), None)
2299 ciphers = connection.get_cipher_list()
2300 self.assertTrue(isinstance(ciphers, list))
2301 for cipher in ciphers:
2302 self.assertTrue(isinstance(cipher, str))
2303
2304
2305
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002306class ConnectionSendTests(TestCase, _LoopbackMixin):
2307 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002308 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002309 """
2310 def test_wrong_args(self):
2311 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002312 When called with arguments other than string argument for its first
2313 parameter or more than two arguments, :py:obj:`Connection.send` raises
2314 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002315 """
2316 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002317 self.assertRaises(TypeError, connection.send)
2318 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002319 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002320
2321
2322 def test_short_bytes(self):
2323 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002324 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002325 and returns the number of bytes sent.
2326 """
2327 server, client = self._loopback()
2328 count = server.send(b('xy'))
2329 self.assertEquals(count, 2)
2330 self.assertEquals(client.recv(2), b('xy'))
2331
2332 try:
2333 memoryview
2334 except NameError:
2335 "cannot test sending memoryview without memoryview"
2336 else:
2337 def test_short_memoryview(self):
2338 """
2339 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002340 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002341 bytes sent.
2342 """
2343 server, client = self._loopback()
2344 count = server.send(memoryview(b('xy')))
2345 self.assertEquals(count, 2)
2346 self.assertEquals(client.recv(2), b('xy'))
2347
2348
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002349 try:
2350 buffer
2351 except NameError:
2352 "cannot test sending buffer without buffer"
2353 else:
2354 def test_short_buffer(self):
2355 """
2356 When passed a buffer containing a small number of bytes,
2357 :py:obj:`Connection.send` transmits all of them and returns the number of
2358 bytes sent.
2359 """
2360 server, client = self._loopback()
2361 count = server.send(buffer(b('xy')))
2362 self.assertEquals(count, 2)
2363 self.assertEquals(client.recv(2), b('xy'))
2364
2365
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002366
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002367class ConnectionSendallTests(TestCase, _LoopbackMixin):
2368 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002369 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002370 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002371 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002372 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002373 When called with arguments other than a string argument for its first
2374 parameter or with more than two arguments, :py:obj:`Connection.sendall`
2375 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002376 """
2377 connection = Connection(Context(TLSv1_METHOD), None)
2378 self.assertRaises(TypeError, connection.sendall)
2379 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002380 self.assertRaises(
2381 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002382
2383
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002384 def test_short(self):
2385 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002386 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002387 it.
2388 """
2389 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04002390 server.sendall(b('x'))
2391 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002392
2393
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002394 try:
2395 memoryview
2396 except NameError:
2397 "cannot test sending memoryview without memoryview"
2398 else:
2399 def test_short_memoryview(self):
2400 """
2401 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002402 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002403 """
2404 server, client = self._loopback()
2405 server.sendall(memoryview(b('x')))
2406 self.assertEquals(client.recv(1), b('x'))
2407
2408
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002409 try:
2410 buffer
2411 except NameError:
2412 "cannot test sending buffers without buffers"
2413 else:
2414 def test_short_buffers(self):
2415 """
2416 When passed a buffer containing a small number of bytes,
2417 :py:obj:`Connection.sendall` transmits all of them.
2418 """
2419 server, client = self._loopback()
2420 server.sendall(buffer(b('x')))
2421 self.assertEquals(client.recv(1), b('x'))
2422
2423
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002424 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002425 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002426 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002427 it even if this requires multiple calls of an underlying write function.
2428 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002429 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04002430 # Should be enough, underlying SSL_write should only do 16k at a time.
2431 # On Windows, after 32k of bytes the write will block (forever - because
2432 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04002433 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002434 server.sendall(message)
2435 accum = []
2436 received = 0
2437 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04002438 data = client.recv(1024)
2439 accum.append(data)
2440 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04002441 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002442
2443
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002444 def test_closed(self):
2445 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002446 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002447 write error from the low level write call.
2448 """
2449 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04002450 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002451 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02002452 if platform == "win32":
2453 self.assertEqual(exc.args[0], ESHUTDOWN)
2454 else:
2455 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002456
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002457
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002458
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002459class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
2460 """
2461 Tests for SSL renegotiation APIs.
2462 """
2463 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002464 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002465 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002466 arguments.
2467 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002468 connection = Connection(Context(TLSv1_METHOD), None)
2469 self.assertRaises(TypeError, connection.renegotiate, None)
2470
2471
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002472 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002473 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002474 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002475 any arguments.
2476 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002477 connection = Connection(Context(TLSv1_METHOD), None)
2478 self.assertRaises(TypeError, connection.total_renegotiations, None)
2479
2480
2481 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002482 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002483 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002484 renegotiations have happened.
2485 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002486 connection = Connection(Context(TLSv1_METHOD), None)
2487 self.assertEquals(connection.total_renegotiations(), 0)
2488
2489
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002490# def test_renegotiate(self):
2491# """
2492# """
2493# server, client = self._loopback()
2494
2495# server.send("hello world")
2496# self.assertEquals(client.recv(len("hello world")), "hello world")
2497
2498# self.assertEquals(server.total_renegotiations(), 0)
2499# self.assertTrue(server.renegotiate())
2500
2501# server.setblocking(False)
2502# client.setblocking(False)
2503# while server.renegotiate_pending():
2504# client.do_handshake()
2505# server.do_handshake()
2506
2507# self.assertEquals(server.total_renegotiations(), 1)
2508
2509
2510
2511
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002512class ErrorTests(TestCase):
2513 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002514 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002515 """
2516 def test_type(self):
2517 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002518 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002519 """
2520 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05002521 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05002522
2523
2524
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002525class ConstantsTests(TestCase):
2526 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002527 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002528
2529 These are values defined by OpenSSL intended only to be used as flags to
2530 OpenSSL APIs. The only assertions it seems can be made about them is
2531 their values.
2532 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002533 # unittest.TestCase has no skip mechanism
2534 if OP_NO_QUERY_MTU is not None:
2535 def test_op_no_query_mtu(self):
2536 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002537 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002538 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002539 """
2540 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
2541 else:
2542 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002543
2544
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002545 if OP_COOKIE_EXCHANGE is not None:
2546 def test_op_cookie_exchange(self):
2547 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002548 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002549 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002550 """
2551 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
2552 else:
2553 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002554
2555
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002556 if OP_NO_TICKET is not None:
2557 def test_op_no_ticket(self):
2558 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002559 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002560 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002561 """
2562 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04002563 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002564 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05002565
2566
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002567 if OP_NO_COMPRESSION is not None:
2568 def test_op_no_compression(self):
2569 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002570 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
2571 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002572 """
2573 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
2574 else:
2575 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
2576
2577
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002578 def test_sess_cache_off(self):
2579 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002580 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
2581 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002582 """
2583 self.assertEqual(0x0, SESS_CACHE_OFF)
2584
2585
2586 def test_sess_cache_client(self):
2587 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002588 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
2589 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002590 """
2591 self.assertEqual(0x1, SESS_CACHE_CLIENT)
2592
2593
2594 def test_sess_cache_server(self):
2595 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002596 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
2597 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002598 """
2599 self.assertEqual(0x2, SESS_CACHE_SERVER)
2600
2601
2602 def test_sess_cache_both(self):
2603 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002604 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
2605 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002606 """
2607 self.assertEqual(0x3, SESS_CACHE_BOTH)
2608
2609
2610 def test_sess_cache_no_auto_clear(self):
2611 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002612 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
2613 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
2614 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002615 """
2616 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
2617
2618
2619 def test_sess_cache_no_internal_lookup(self):
2620 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002621 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
2622 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
2623 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002624 """
2625 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
2626
2627
2628 def test_sess_cache_no_internal_store(self):
2629 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002630 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
2631 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
2632 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002633 """
2634 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
2635
2636
2637 def test_sess_cache_no_internal(self):
2638 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002639 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
2640 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
2641 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002642 """
2643 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
2644
2645
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04002646
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002647class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05002648 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002649 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05002650 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002651 def _server(self, sock):
2652 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002653 Create a new server-side SSL :py:obj:`Connection` object wrapped around
2654 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002655 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002656 # Create the server side Connection. This is mostly setup boilerplate
2657 # - use TLSv1, use a particular certificate, etc.
2658 server_ctx = Context(TLSv1_METHOD)
2659 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2660 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2661 server_store = server_ctx.get_cert_store()
2662 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2663 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2664 server_ctx.check_privatekey()
2665 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002666 # Here the Connection is actually created. If None is passed as the 2nd
2667 # parameter, it indicates a memory BIO should be created.
2668 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002669 server_conn.set_accept_state()
2670 return server_conn
2671
2672
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002673 def _client(self, sock):
2674 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002675 Create a new client-side SSL :py:obj:`Connection` object wrapped around
2676 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002677 """
2678 # Now create the client side Connection. Similar boilerplate to the
2679 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002680 client_ctx = Context(TLSv1_METHOD)
2681 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2682 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2683 client_store = client_ctx.get_cert_store()
2684 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
2685 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
2686 client_ctx.check_privatekey()
2687 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002688 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002689 client_conn.set_connect_state()
2690 return client_conn
2691
2692
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002693 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002694 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002695 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002696 reading from the output of each and writing those bytes to the input of
2697 the other and in this way establish a connection and exchange
2698 application-level bytes with each other.
2699 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002700 server_conn = self._server(None)
2701 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002702
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002703 # There should be no key or nonces yet.
2704 self.assertIdentical(server_conn.master_key(), None)
2705 self.assertIdentical(server_conn.client_random(), None)
2706 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002707
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002708 # First, the handshake needs to happen. We'll deliver bytes back and
2709 # forth between the client and server until neither of them feels like
2710 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002711 self.assertIdentical(
2712 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002713
2714 # Now that the handshake is done, there should be a key and nonces.
2715 self.assertNotIdentical(server_conn.master_key(), None)
2716 self.assertNotIdentical(server_conn.client_random(), None)
2717 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04002718 self.assertEquals(server_conn.client_random(), client_conn.client_random())
2719 self.assertEquals(server_conn.server_random(), client_conn.server_random())
2720 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
2721 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002722
2723 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002724 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05002725
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002726 server_conn.write(important_message)
2727 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002728 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002729 (client_conn, important_message))
2730
2731 client_conn.write(important_message[::-1])
2732 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002733 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002734 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05002735
2736
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002737 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05002738 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002739 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002740
2741 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09002742 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002743 this test fails, there must be a problem outside the memory BIO
2744 code, as no memory BIO is involved here). Even though this isn't a
2745 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05002746 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04002747 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05002748
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002749 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05002750 client_conn.send(important_message)
2751 msg = server_conn.recv(1024)
2752 self.assertEqual(msg, important_message)
2753
2754 # Again in the other direction, just for fun.
2755 important_message = important_message[::-1]
2756 server_conn.send(important_message)
2757 msg = client_conn.recv(1024)
2758 self.assertEqual(msg, important_message)
2759
2760
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04002761 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05002762 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002763 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
2764 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05002765 """
2766 context = Context(SSLv3_METHOD)
2767 client = socket()
2768 clientSSL = Connection(context, client)
2769 self.assertRaises( TypeError, clientSSL.bio_read, 100)
2770 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04002771 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002772
2773
2774 def test_outgoingOverflow(self):
2775 """
2776 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002777 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002778 returned and that many bytes from the beginning of the input can be
2779 read from the other end of the connection.
2780 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002781 server = self._server(None)
2782 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002783
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002784 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002785
2786 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002787 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002788 # Sanity check. We're trying to test what happens when the entire
2789 # input can't be sent. If the entire input was sent, this test is
2790 # meaningless.
2791 self.assertTrue(sent < size)
2792
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002793 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002794 self.assertIdentical(receiver, server)
2795
2796 # We can rely on all of these bytes being received at once because
2797 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
2798 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002799
2800
2801 def test_shutdown(self):
2802 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002803 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
2804 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002805 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002806 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002807 server.bio_shutdown()
2808 e = self.assertRaises(Error, server.recv, 1024)
2809 # We don't want WantReadError or ZeroReturnError or anything - it's a
2810 # handshake failure.
2811 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002812
2813
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002814 def test_unexpectedEndOfFile(self):
2815 """
2816 If the connection is lost before an orderly SSL shutdown occurs,
2817 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
2818 "Unexpected EOF".
2819 """
2820 server_conn, client_conn = self._loopback()
2821 client_conn.sock_shutdown(SHUT_RDWR)
2822 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
2823 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
2824
2825
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002826 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002827 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002828 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 -04002829
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002830 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002831 before the client and server are connected to each other. This
2832 function should specify a list of CAs for the server to send to the
2833 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09002834 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002835 times.
2836 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002837 server = self._server(None)
2838 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002839 self.assertEqual(client.get_client_ca_list(), [])
2840 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002841 ctx = server.get_context()
2842 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002843 self.assertEqual(client.get_client_ca_list(), [])
2844 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002845 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002846 self.assertEqual(client.get_client_ca_list(), expected)
2847 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002848
2849
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002850 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002851 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002852 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002853 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002854 """
2855 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002856 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
2857 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
2858 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002859
2860
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002861 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002862 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002863 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002864 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09002865 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002866 after the connection is set up.
2867 """
2868 def no_ca(ctx):
2869 ctx.set_client_ca_list([])
2870 return []
2871 self._check_client_ca_list(no_ca)
2872
2873
2874 def test_set_one_ca_list(self):
2875 """
2876 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002877 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002878 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002879 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002880 X509Name after the connection is set up.
2881 """
2882 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2883 cadesc = cacert.get_subject()
2884 def single_ca(ctx):
2885 ctx.set_client_ca_list([cadesc])
2886 return [cadesc]
2887 self._check_client_ca_list(single_ca)
2888
2889
2890 def test_set_multiple_ca_list(self):
2891 """
2892 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002893 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002894 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002895 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002896 X509Names after the connection is set up.
2897 """
2898 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2899 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2900
2901 sedesc = secert.get_subject()
2902 cldesc = clcert.get_subject()
2903
2904 def multiple_ca(ctx):
2905 L = [sedesc, cldesc]
2906 ctx.set_client_ca_list(L)
2907 return L
2908 self._check_client_ca_list(multiple_ca)
2909
2910
2911 def test_reset_ca_list(self):
2912 """
2913 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09002914 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002915 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002916 """
2917 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2918 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2919 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2920
2921 cadesc = cacert.get_subject()
2922 sedesc = secert.get_subject()
2923 cldesc = clcert.get_subject()
2924
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002925 def changed_ca(ctx):
2926 ctx.set_client_ca_list([sedesc, cldesc])
2927 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002928 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002929 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002930
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002931
2932 def test_mutated_ca_list(self):
2933 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002934 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002935 afterwards, this does not affect the list of CA names sent to the
2936 client.
2937 """
2938 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2939 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2940
2941 cadesc = cacert.get_subject()
2942 sedesc = secert.get_subject()
2943
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002944 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002945 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002946 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002947 L.append(sedesc)
2948 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002949 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002950
2951
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002952 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002953 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002954 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002955 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002956 """
2957 ctx = Context(TLSv1_METHOD)
2958 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002959 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002960 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002961 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002962
2963
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002964 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002965 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002966 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09002967 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002968 """
2969 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2970 cadesc = cacert.get_subject()
2971 def single_ca(ctx):
2972 ctx.add_client_ca(cacert)
2973 return [cadesc]
2974 self._check_client_ca_list(single_ca)
2975
2976
2977 def test_multiple_add_client_ca(self):
2978 """
2979 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09002980 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002981 """
2982 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2983 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2984
2985 cadesc = cacert.get_subject()
2986 sedesc = secert.get_subject()
2987
2988 def multiple_ca(ctx):
2989 ctx.add_client_ca(cacert)
2990 ctx.add_client_ca(secert)
2991 return [cadesc, sedesc]
2992 self._check_client_ca_list(multiple_ca)
2993
2994
2995 def test_set_and_add_client_ca(self):
2996 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002997 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
2998 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002999 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003000 """
3001 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3002 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3003 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3004
3005 cadesc = cacert.get_subject()
3006 sedesc = secert.get_subject()
3007 cldesc = clcert.get_subject()
3008
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003009 def mixed_set_add_ca(ctx):
3010 ctx.set_client_ca_list([cadesc, sedesc])
3011 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003012 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003013 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003014
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003015
3016 def test_set_after_add_client_ca(self):
3017 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003018 A call to :py:obj:`Context.set_client_ca_list` after a call to
3019 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003020 call with the names specified by the latter cal.
3021 """
3022 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3023 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3024 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3025
3026 cadesc = cacert.get_subject()
3027 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003028
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003029 def set_replaces_add_ca(ctx):
3030 ctx.add_client_ca(clcert)
3031 ctx.set_client_ca_list([cadesc])
3032 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003033 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003034 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003035
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003036
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003037
3038class ConnectionBIOTests(TestCase):
3039 """
3040 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3041 """
3042 def test_wantReadError(self):
3043 """
3044 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
3045 if there are no bytes available to be read from the BIO.
3046 """
3047 ctx = Context(TLSv1_METHOD)
3048 conn = Connection(ctx, None)
3049 self.assertRaises(WantReadError, conn.bio_read, 1024)
3050
3051
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003052 def test_buffer_size(self):
3053 """
3054 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3055 number of bytes to read and return.
3056 """
3057 ctx = Context(TLSv1_METHOD)
3058 conn = Connection(ctx, None)
3059 conn.set_connect_state()
3060 try:
3061 conn.do_handshake()
3062 except WantReadError:
3063 pass
3064 data = conn.bio_read(2)
3065 self.assertEqual(2, len(data))
3066
3067
3068 if not PY3:
3069 def test_buffer_size_long(self):
3070 """
3071 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3072 :py:obj:`long` as well as :py:obj:`int`.
3073 """
3074 ctx = Context(TLSv1_METHOD)
3075 conn = Connection(ctx, None)
3076 conn.set_connect_state()
3077 try:
3078 conn.do_handshake()
3079 except WantReadError:
3080 pass
3081 data = conn.bio_read(long(2))
3082 self.assertEqual(2, len(data))
3083
3084
3085
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003086
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003087class InfoConstantTests(TestCase):
3088 """
3089 Tests for assorted constants exposed for use in info callbacks.
3090 """
3091 def test_integers(self):
3092 """
3093 All of the info constants are integers.
3094
3095 This is a very weak test. It would be nice to have one that actually
3096 verifies that as certain info events happen, the value passed to the
3097 info callback matches up with the constant exposed by OpenSSL.SSL.
3098 """
3099 for const in [
3100 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3101 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3102 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3103 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3104 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
3105 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
3106
3107 self.assertTrue(isinstance(const, int))
3108
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003109
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003110if __name__ == '__main__':
3111 main()