blob: 0b6a5ffc476b7041c03c6dc23d74885bb1a9075d [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 Calderonebf37f0f2010-07-31 14:56:20 -040097def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040098 return ok
99
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400100
Rick Deanb1ccd562009-07-09 23:52:39 -0500101def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400102 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400103 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400104 """
105 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500106 port = socket()
107 port.bind(('', 0))
108 port.listen(1)
109 client = socket()
110 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400111 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400112 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500113 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500114
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400115 # Let's pass some unencrypted data to make sure our socket connection is
116 # fine. Just one byte, so we don't have to worry about buffers getting
117 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400118 server.send(b("x"))
119 assert client.recv(1024) == b("x")
120 client.send(b("y"))
121 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500122
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400123 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400124 server.setblocking(False)
125 client.setblocking(False)
126
Rick Deanb1ccd562009-07-09 23:52:39 -0500127 return (server, client)
128
129
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400130
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400131def handshake(client, server):
132 conns = [client, server]
133 while conns:
134 for conn in conns:
135 try:
136 conn.do_handshake()
137 except WantReadError:
138 pass
139 else:
140 conns.remove(conn)
141
142
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400143def _create_certificate_chain():
144 """
145 Construct and return a chain of certificates.
146
147 1. A new self-signed certificate authority certificate (cacert)
148 2. A new intermediate certificate signed by cacert (icert)
149 3. A new server certificate signed by icert (scert)
150 """
151 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
152
153 # Step 1
154 cakey = PKey()
155 cakey.generate_key(TYPE_RSA, 512)
156 cacert = X509()
157 cacert.get_subject().commonName = "Authority Certificate"
158 cacert.set_issuer(cacert.get_subject())
159 cacert.set_pubkey(cakey)
160 cacert.set_notBefore(b("20000101000000Z"))
161 cacert.set_notAfter(b("20200101000000Z"))
162 cacert.add_extensions([caext])
163 cacert.set_serial_number(0)
164 cacert.sign(cakey, "sha1")
165
166 # Step 2
167 ikey = PKey()
168 ikey.generate_key(TYPE_RSA, 512)
169 icert = X509()
170 icert.get_subject().commonName = "Intermediate Certificate"
171 icert.set_issuer(cacert.get_subject())
172 icert.set_pubkey(ikey)
173 icert.set_notBefore(b("20000101000000Z"))
174 icert.set_notAfter(b("20200101000000Z"))
175 icert.add_extensions([caext])
176 icert.set_serial_number(0)
177 icert.sign(cakey, "sha1")
178
179 # Step 3
180 skey = PKey()
181 skey.generate_key(TYPE_RSA, 512)
182 scert = X509()
183 scert.get_subject().commonName = "Server Certificate"
184 scert.set_issuer(icert.get_subject())
185 scert.set_pubkey(skey)
186 scert.set_notBefore(b("20000101000000Z"))
187 scert.set_notAfter(b("20200101000000Z"))
188 scert.add_extensions([
189 X509Extension(b('basicConstraints'), True, b('CA:false'))])
190 scert.set_serial_number(0)
191 scert.sign(ikey, "sha1")
192
193 return [(cakey, cacert), (ikey, icert), (skey, scert)]
194
195
196
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400197class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400198 """
199 Helper mixin which defines methods for creating a connected socket pair and
200 for forcing two connected SSL sockets to talk to each other via memory BIOs.
201 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500202 def _loopbackClientFactory(self, socket):
203 client = Connection(Context(TLSv1_METHOD), socket)
204 client.set_connect_state()
205 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400206
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500207
208 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400209 ctx = Context(TLSv1_METHOD)
210 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
211 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500212 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400213 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500214 return server
215
216
217 def _loopback(self, serverFactory=None, clientFactory=None):
218 if serverFactory is None:
219 serverFactory = self._loopbackServerFactory
220 if clientFactory is None:
221 clientFactory = self._loopbackClientFactory
222
223 (server, client) = socket_pair()
224 server = serverFactory(server)
225 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400226
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400227 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400228
229 server.setblocking(True)
230 client.setblocking(True)
231 return server, client
232
233
234 def _interactInMemory(self, client_conn, server_conn):
235 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900236 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400237 objects. Copy bytes back and forth between their send/receive buffers
238 for as long as there is anything to copy. When there is nothing more
Jonathan Ballet648875f2011-07-16 14:14:58 +0900239 to copy, return :py:obj:`None`. If one of them actually manages to deliver
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400240 some application bytes, return a two-tuple of the connection from which
241 the bytes were read and the bytes themselves.
242 """
243 wrote = True
244 while wrote:
245 # Loop until neither side has anything to say
246 wrote = False
247
248 # Copy stuff from each side's send buffer to the other side's
249 # receive buffer.
250 for (read, write) in [(client_conn, server_conn),
251 (server_conn, client_conn)]:
252
253 # Give the side a chance to generate some more bytes, or
254 # succeed.
255 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400256 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400257 except WantReadError:
258 # It didn't succeed, so we'll hope it generated some
259 # output.
260 pass
261 else:
262 # It did succeed, so we'll stop now and let the caller deal
263 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400264 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400265
266 while True:
267 # Keep copying as long as there's more stuff there.
268 try:
269 dirty = read.bio_read(4096)
270 except WantReadError:
271 # Okay, nothing more waiting to be sent. Stop
272 # processing this send buffer.
273 break
274 else:
275 # Keep track of the fact that someone generated some
276 # output.
277 wrote = True
278 write.bio_write(dirty)
279
280
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400281 def _handshakeInMemory(self, client_conn, server_conn):
Jean-Paul Calderoneb2b40782014-05-06 08:47:40 -0400282 """
283 Perform the TLS handshake between two :py:class:`Connection` instances
284 connected to each other via memory BIOs.
285 """
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400286 client_conn.set_connect_state()
287 server_conn.set_accept_state()
288
289 for conn in [client_conn, server_conn]:
290 try:
291 conn.do_handshake()
292 except WantReadError:
293 pass
294
295 self._interactInMemory(client_conn, server_conn)
296
297
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400298
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400299class VersionTests(TestCase):
300 """
301 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900302 :py:obj:`OpenSSL.SSL.SSLeay_version` and
303 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400304 """
305 def test_OPENSSL_VERSION_NUMBER(self):
306 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900307 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400308 byte and the patch, fix, minor, and major versions in the
309 nibbles above that.
310 """
311 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
312
313
314 def test_SSLeay_version(self):
315 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900316 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400317 one of a number of version strings based on that indicator.
318 """
319 versions = {}
320 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
321 SSLEAY_PLATFORM, SSLEAY_DIR]:
322 version = SSLeay_version(t)
323 versions[version] = t
324 self.assertTrue(isinstance(version, bytes))
325 self.assertEqual(len(versions), 5)
326
327
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400328
329class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400330 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900331 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400332 """
333 def test_method(self):
334 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900335 :py:obj:`Context` can be instantiated with one of :py:obj:`SSLv2_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400336 :py:obj:`SSLv3_METHOD`, :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
337 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400338 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400339 methods = [
340 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
341 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400342 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400343
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400344
345 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
346 for meth in maybe:
347 try:
348 Context(meth)
349 except (Error, ValueError):
350 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
351 # don't. Difficult to say in advance.
352 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400353
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400354 self.assertRaises(TypeError, Context, "")
355 self.assertRaises(ValueError, Context, 10)
356
357
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500358 if not PY3:
359 def test_method_long(self):
360 """
361 On Python 2 :py:class:`Context` accepts values of type
362 :py:obj:`long` as well as :py:obj:`int`.
363 """
364 Context(long(TLSv1_METHOD))
365
366
367
Rick Deane15b1472009-07-09 15:53:42 -0500368 def test_type(self):
369 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900370 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400371 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500372 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400373 self.assertIdentical(Context, ContextType)
374 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500375
376
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400377 def test_use_privatekey(self):
378 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900379 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400380 """
381 key = PKey()
382 key.generate_key(TYPE_RSA, 128)
383 ctx = Context(TLSv1_METHOD)
384 ctx.use_privatekey(key)
385 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400386
387
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800388 def test_use_privatekey_file_missing(self):
389 """
390 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error`
391 when passed the name of a file which does not exist.
392 """
393 ctx = Context(TLSv1_METHOD)
394 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
395
396
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500397 if not PY3:
398 def test_use_privatekey_file_long(self):
399 """
400 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
401 filetype of type :py:obj:`long` as well as :py:obj:`int`.
402 """
403 pemfile = self.mktemp()
404
405 key = PKey()
406 key.generate_key(TYPE_RSA, 128)
407
408 with open(pemfile, "wt") as pem:
409 pem.write(
410 dump_privatekey(FILETYPE_PEM, key).decode("ascii"))
411
412 ctx = Context(TLSv1_METHOD)
413 ctx.use_privatekey_file(pemfile, long(FILETYPE_PEM))
414
415
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800416 def test_use_certificate_wrong_args(self):
417 """
418 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
419 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as an
420 argument.
421 """
422 ctx = Context(TLSv1_METHOD)
423 self.assertRaises(TypeError, ctx.use_certificate)
424 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
425 self.assertRaises(TypeError, ctx.use_certificate, X509(), "hello, world")
426
427
428 def test_use_certificate_uninitialized(self):
429 """
430 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
431 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
432 initialized (ie, which does not actually have any certificate data).
433 """
434 ctx = Context(TLSv1_METHOD)
435 self.assertRaises(Error, ctx.use_certificate, X509())
436
437
438 def test_use_certificate(self):
439 """
440 :py:obj:`Context.use_certificate` sets the certificate which will be
441 used to identify connections created using the context.
442 """
443 # TODO
444 # Hard to assert anything. But we could set a privatekey then ask
445 # OpenSSL if the cert and key agree using check_privatekey. Then as
446 # long as check_privatekey works right we're good...
447 ctx = Context(TLSv1_METHOD)
448 ctx.use_certificate(load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
449
450
451 def test_use_certificate_file_wrong_args(self):
452 """
453 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
454 called with zero arguments or more than two arguments, or if the first
455 argument is not a byte string or the second argumnent is not an integer.
456 """
457 ctx = Context(TLSv1_METHOD)
458 self.assertRaises(TypeError, ctx.use_certificate_file)
459 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile", object())
460 self.assertRaises(
461 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM, object())
462 self.assertRaises(
463 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
464 self.assertRaises(
465 TypeError, ctx.use_certificate_file, b"somefile", object())
466
467
468 def test_use_certificate_file_missing(self):
469 """
470 :py:obj:`Context.use_certificate_file` raises
471 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does not
472 exist.
473 """
474 ctx = Context(TLSv1_METHOD)
475 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
476
477
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400478 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800479 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400480 Verify that calling ``Context.use_certificate_file`` with the given
481 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800482 """
483 # TODO
484 # Hard to assert anything. But we could set a privatekey then ask
485 # OpenSSL if the cert and key agree using check_privatekey. Then as
486 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400487 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800488 pem_file.write(cleartextCertificatePEM)
489
490 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400491 ctx.use_certificate_file(certificate_file)
492
493
494 def test_use_certificate_file_bytes(self):
495 """
496 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
497 ``bytes`` filename) which will be used to identify connections created
498 using the context.
499 """
500 filename = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
501 self._use_certificate_file_test(filename)
502
503
504 def test_use_certificate_file_unicode(self):
505 """
506 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
507 ``bytes`` filename) which will be used to identify connections created
508 using the context.
509 """
510 filename = self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
511 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800512
513
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500514 if not PY3:
515 def test_use_certificate_file_long(self):
516 """
517 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
518 filetype of type :py:obj:`long` as well as :py:obj:`int`.
519 """
520 pem_filename = self.mktemp()
521 with open(pem_filename, "wb") as pem_file:
522 pem_file.write(cleartextCertificatePEM)
523
524 ctx = Context(TLSv1_METHOD)
525 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
526
527
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400528 def test_set_app_data_wrong_args(self):
529 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900530 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called with other than
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400531 one argument.
532 """
533 context = Context(TLSv1_METHOD)
534 self.assertRaises(TypeError, context.set_app_data)
535 self.assertRaises(TypeError, context.set_app_data, None, None)
536
537
538 def test_get_app_data_wrong_args(self):
539 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900540 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400541 arguments.
542 """
543 context = Context(TLSv1_METHOD)
544 self.assertRaises(TypeError, context.get_app_data, None)
545
546
547 def test_app_data(self):
548 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900549 :py:obj:`Context.set_app_data` stores an object for later retrieval using
550 :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400551 """
552 app_data = object()
553 context = Context(TLSv1_METHOD)
554 context.set_app_data(app_data)
555 self.assertIdentical(context.get_app_data(), app_data)
556
557
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400558 def test_set_options_wrong_args(self):
559 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900560 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with the wrong
561 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400562 """
563 context = Context(TLSv1_METHOD)
564 self.assertRaises(TypeError, context.set_options)
565 self.assertRaises(TypeError, context.set_options, None)
566 self.assertRaises(TypeError, context.set_options, 1, None)
567
568
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500569 def test_set_options(self):
570 """
571 :py:obj:`Context.set_options` returns the new options value.
572 """
573 context = Context(TLSv1_METHOD)
574 options = context.set_options(OP_NO_SSLv2)
575 self.assertTrue(OP_NO_SSLv2 & options)
576
577
578 if not PY3:
579 def test_set_options_long(self):
580 """
581 On Python 2 :py:obj:`Context.set_options` accepts values of type
582 :py:obj:`long` as well as :py:obj:`int`.
583 """
584 context = Context(TLSv1_METHOD)
585 options = context.set_options(long(OP_NO_SSLv2))
586 self.assertTrue(OP_NO_SSLv2 & options)
587
588
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300589 def test_set_mode_wrong_args(self):
590 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400591 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with the wrong
592 number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300593 """
594 context = Context(TLSv1_METHOD)
595 self.assertRaises(TypeError, context.set_mode)
596 self.assertRaises(TypeError, context.set_mode, None)
597 self.assertRaises(TypeError, context.set_mode, 1, None)
598
599
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400600 if MODE_RELEASE_BUFFERS is not None:
601 def test_set_mode(self):
602 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400603 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the newly
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400604 set mode.
605 """
606 context = Context(TLSv1_METHOD)
607 self.assertTrue(
608 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500609
610 if not PY3:
611 def test_set_mode_long(self):
612 """
613 On Python 2 :py:obj:`Context.set_mode` accepts values of type
614 :py:obj:`long` as well as :py:obj:`int`.
615 """
616 context = Context(TLSv1_METHOD)
617 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
618 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400619 else:
620 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
621
622
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400623 def test_set_timeout_wrong_args(self):
624 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900625 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with the wrong
626 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400627 """
628 context = Context(TLSv1_METHOD)
629 self.assertRaises(TypeError, context.set_timeout)
630 self.assertRaises(TypeError, context.set_timeout, None)
631 self.assertRaises(TypeError, context.set_timeout, 1, None)
632
633
634 def test_get_timeout_wrong_args(self):
635 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900636 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400637 """
638 context = Context(TLSv1_METHOD)
639 self.assertRaises(TypeError, context.get_timeout, None)
640
641
642 def test_timeout(self):
643 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900644 :py:obj:`Context.set_timeout` sets the session timeout for all connections
645 created using the context object. :py:obj:`Context.get_timeout` retrieves this
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400646 value.
647 """
648 context = Context(TLSv1_METHOD)
649 context.set_timeout(1234)
650 self.assertEquals(context.get_timeout(), 1234)
651
652
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500653 if not PY3:
654 def test_timeout_long(self):
655 """
656 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
657 `long` as well as int.
658 """
659 context = Context(TLSv1_METHOD)
660 context.set_timeout(long(1234))
661 self.assertEquals(context.get_timeout(), 1234)
662
663
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400664 def test_set_verify_depth_wrong_args(self):
665 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900666 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called with the wrong
667 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400668 """
669 context = Context(TLSv1_METHOD)
670 self.assertRaises(TypeError, context.set_verify_depth)
671 self.assertRaises(TypeError, context.set_verify_depth, None)
672 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
673
674
675 def test_get_verify_depth_wrong_args(self):
676 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900677 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400678 """
679 context = Context(TLSv1_METHOD)
680 self.assertRaises(TypeError, context.get_verify_depth, None)
681
682
683 def test_verify_depth(self):
684 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900685 :py:obj:`Context.set_verify_depth` sets the number of certificates in a chain
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400686 to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900687 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400688 """
689 context = Context(TLSv1_METHOD)
690 context.set_verify_depth(11)
691 self.assertEquals(context.get_verify_depth(), 11)
692
693
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500694 if not PY3:
695 def test_verify_depth_long(self):
696 """
697 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
698 type `long` as well as int.
699 """
700 context = Context(TLSv1_METHOD)
701 context.set_verify_depth(long(11))
702 self.assertEquals(context.get_verify_depth(), 11)
703
704
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400705 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400706 """
707 Write a new private key out to a new file, encrypted using the given
708 passphrase. Return the path to the new file.
709 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400710 key = PKey()
711 key.generate_key(TYPE_RSA, 128)
712 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400713 fObj = open(pemFile, 'w')
714 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
715 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400716 fObj.close()
717 return pemFile
718
719
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400720 def test_set_passwd_cb_wrong_args(self):
721 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900722 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called with the
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400723 wrong arguments or with a non-callable first argument.
724 """
725 context = Context(TLSv1_METHOD)
726 self.assertRaises(TypeError, context.set_passwd_cb)
727 self.assertRaises(TypeError, context.set_passwd_cb, None)
728 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
729
730
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400731 def test_set_passwd_cb(self):
732 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900733 :py:obj:`Context.set_passwd_cb` accepts a callable which will be invoked when
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400734 a private key is loaded from an encrypted PEM.
735 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400736 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400737 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400738 calledWith = []
739 def passphraseCallback(maxlen, verify, extra):
740 calledWith.append((maxlen, verify, extra))
741 return passphrase
742 context = Context(TLSv1_METHOD)
743 context.set_passwd_cb(passphraseCallback)
744 context.use_privatekey_file(pemFile)
745 self.assertTrue(len(calledWith), 1)
746 self.assertTrue(isinstance(calledWith[0][0], int))
747 self.assertTrue(isinstance(calledWith[0][1], int))
748 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400749
750
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400751 def test_passwd_callback_exception(self):
752 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900753 :py:obj:`Context.use_privatekey_file` propagates any exception raised by the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400754 passphrase callback.
755 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400756 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400757 def passphraseCallback(maxlen, verify, extra):
758 raise RuntimeError("Sorry, I am a fail.")
759
760 context = Context(TLSv1_METHOD)
761 context.set_passwd_cb(passphraseCallback)
762 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
763
764
765 def test_passwd_callback_false(self):
766 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900767 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400768 passphrase callback returns a false value.
769 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400770 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400771 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500772 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400773
774 context = Context(TLSv1_METHOD)
775 context.set_passwd_cb(passphraseCallback)
776 self.assertRaises(Error, context.use_privatekey_file, pemFile)
777
778
779 def test_passwd_callback_non_string(self):
780 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900781 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400782 passphrase callback returns a true non-string value.
783 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400784 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400785 def passphraseCallback(maxlen, verify, extra):
786 return 10
787
788 context = Context(TLSv1_METHOD)
789 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800790 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400791
792
793 def test_passwd_callback_too_long(self):
794 """
795 If the passphrase returned by the passphrase callback returns a string
796 longer than the indicated maximum length, it is truncated.
797 """
798 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400799 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400800 pemFile = self._write_encrypted_pem(passphrase)
801 def passphraseCallback(maxlen, verify, extra):
802 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400803 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400804
805 context = Context(TLSv1_METHOD)
806 context.set_passwd_cb(passphraseCallback)
807 # This shall succeed because the truncated result is the correct
808 # passphrase.
809 context.use_privatekey_file(pemFile)
810
811
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400812 def test_set_info_callback(self):
813 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900814 :py:obj:`Context.set_info_callback` accepts a callable which will be invoked
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400815 when certain information about an SSL connection is available.
816 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500817 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400818
819 clientSSL = Connection(Context(TLSv1_METHOD), client)
820 clientSSL.set_connect_state()
821
822 called = []
823 def info(conn, where, ret):
824 called.append((conn, where, ret))
825 context = Context(TLSv1_METHOD)
826 context.set_info_callback(info)
827 context.use_certificate(
828 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
829 context.use_privatekey(
830 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
831
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400832 serverSSL = Connection(context, server)
833 serverSSL.set_accept_state()
834
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500835 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400836
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500837 # The callback must always be called with a Connection instance as the
838 # first argument. It would probably be better to split this into
839 # separate tests for client and server side info callbacks so we could
840 # assert it is called with the right Connection instance. It would
841 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500842 notConnections = [
843 conn for (conn, where, ret) in called
844 if not isinstance(conn, Connection)]
845 self.assertEqual(
846 [], notConnections,
847 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400848
849
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400850 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400851 """
852 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400853 its :py:obj:`load_verify_locations` method with the given arguments.
854 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400855 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500856 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400857
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400858 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400859 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400860 # Require that the server certificate verify properly or the
861 # connection will fail.
862 clientContext.set_verify(
863 VERIFY_PEER,
864 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
865
866 clientSSL = Connection(clientContext, client)
867 clientSSL.set_connect_state()
868
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400869 serverContext = Context(TLSv1_METHOD)
870 serverContext.use_certificate(
871 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
872 serverContext.use_privatekey(
873 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
874
875 serverSSL = Connection(serverContext, server)
876 serverSSL.set_accept_state()
877
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400878 # Without load_verify_locations above, the handshake
879 # will fail:
880 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
881 # 'certificate verify failed')]
882 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400883
884 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400885 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400886
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500887
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400888 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400889 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400890 Verify that if path to a file containing a certificate is passed to
891 ``Context.load_verify_locations`` for the ``cafile`` parameter, that
892 certificate is used as a trust root for the purposes of verifying
893 connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400894 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400895 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400896 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400897 fObj.close()
898
899 self._load_verify_locations_test(cafile)
900
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400901
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400902 def test_load_verify_bytes_cafile(self):
903 """
904 :py:obj:`Context.load_verify_locations` accepts a file name as a
905 ``bytes`` instance and uses the certificates within for verification
906 purposes.
907 """
908 cafile = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
909 self._load_verify_cafile(cafile)
910
911
912 def test_load_verify_unicode_cafile(self):
913 """
914 :py:obj:`Context.load_verify_locations` accepts a file name as a
915 ``unicode`` instance and uses the certificates within for verification
916 purposes.
917 """
918 cafile = self.mktemp() + NON_ASCII
919 self._load_verify_cafile(cafile)
920
921
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400922 def test_load_verify_invalid_file(self):
923 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900924 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when passed a
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400925 non-existent cafile.
926 """
927 clientContext = Context(TLSv1_METHOD)
928 self.assertRaises(
929 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400930
931
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400932 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400933 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400934 Verify that if path to a directory containing certificate files is
935 passed to ``Context.load_verify_locations`` for the ``capath``
936 parameter, those certificates are used as trust roots for the purposes
937 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400938 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400939 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400940 # Hash values computed manually with c_rehash to avoid depending on
941 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
942 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500943 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400944 cafile = join(capath, name)
945 fObj = open(cafile, 'w')
946 fObj.write(cleartextCertificatePEM.decode('ascii'))
947 fObj.close()
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400948
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400949 self._load_verify_locations_test(None, capath)
950
951
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400952 def test_load_verify_directory_bytes_capath(self):
953 """
954 :py:obj:`Context.load_verify_locations` accepts a directory name as a
955 ``bytes`` instance and uses the certificates within for verification
956 purposes.
957 """
958 self._load_verify_directory_locations_capath(
959 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
960 )
961
962
963 def test_load_verify_directory_unicode_capath(self):
964 """
965 :py:obj:`Context.load_verify_locations` accepts a directory name as a
966 ``unicode`` instance and uses the certificates within for verification
967 purposes.
968 """
969 self._load_verify_directory_locations_capath(self.mktemp() + NON_ASCII)
970
971
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400972 def test_load_verify_locations_wrong_args(self):
973 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900974 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if called with
975 the wrong number of arguments or with non-:py:obj:`str` arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400976 """
977 context = Context(TLSv1_METHOD)
978 self.assertRaises(TypeError, context.load_verify_locations)
979 self.assertRaises(TypeError, context.load_verify_locations, object())
980 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
981 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
982
983
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400984 if platform == "win32":
985 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400986 "See LP#404343 and LP#404344."
987 else:
988 def test_set_default_verify_paths(self):
989 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900990 :py:obj:`Context.set_default_verify_paths` causes the platform-specific CA
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400991 certificate locations to be used for verification purposes.
992 """
993 # Testing this requires a server with a certificate signed by one of
994 # the CAs in the platform CA location. Getting one of those costs
995 # money. Fortunately (or unfortunately, depending on your
996 # perspective), it's easy to think of a public server on the
997 # internet which has such a certificate. Connecting to the network
998 # in a unit test is bad, but it's the only way I can think of to
999 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001000
Alex Gaynorb586da32014-11-15 09:22:21 -08001001 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
1002 context = Context(TLSv1_METHOD)
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001003 context.set_default_verify_paths()
1004 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02001005 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001006 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001007
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001008 client = socket()
1009 client.connect(('verisign.com', 443))
1010 clientSSL = Connection(context, client)
1011 clientSSL.set_connect_state()
1012 clientSSL.do_handshake()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001013 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001014 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001015
1016
1017 def test_set_default_verify_paths_signature(self):
1018 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001019 :py:obj:`Context.set_default_verify_paths` takes no arguments and raises
1020 :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001021 """
1022 context = Context(TLSv1_METHOD)
1023 self.assertRaises(TypeError, context.set_default_verify_paths, None)
1024 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
1025 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001026
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001027
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001028 def test_add_extra_chain_cert_invalid_cert(self):
1029 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001030 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if called with
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001031 other than one argument or if called with an object which is not an
Jonathan Ballet648875f2011-07-16 14:14:58 +09001032 instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001033 """
1034 context = Context(TLSv1_METHOD)
1035 self.assertRaises(TypeError, context.add_extra_chain_cert)
1036 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
1037 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
1038
1039
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001040 def _handshake_test(self, serverContext, clientContext):
1041 """
1042 Verify that a client and server created with the given contexts can
1043 successfully handshake and communicate.
1044 """
1045 serverSocket, clientSocket = socket_pair()
1046
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001047 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001048 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001049
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001050 client = Connection(clientContext, clientSocket)
1051 client.set_connect_state()
1052
1053 # Make them talk to each other.
1054 # self._interactInMemory(client, server)
1055 for i in range(3):
1056 for s in [client, server]:
1057 try:
1058 s.do_handshake()
1059 except WantReadError:
1060 pass
1061
1062
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001063 def test_set_verify_callback_connection_argument(self):
1064 """
1065 The first argument passed to the verify callback is the
1066 :py:class:`Connection` instance for which verification is taking place.
1067 """
1068 serverContext = Context(TLSv1_METHOD)
1069 serverContext.use_privatekey(
1070 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1071 serverContext.use_certificate(
1072 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1073 serverConnection = Connection(serverContext, None)
1074
1075 class VerifyCallback(object):
1076 def callback(self, connection, *args):
1077 self.connection = connection
1078 return 1
1079
1080 verify = VerifyCallback()
1081 clientContext = Context(TLSv1_METHOD)
1082 clientContext.set_verify(VERIFY_PEER, verify.callback)
1083 clientConnection = Connection(clientContext, None)
1084 clientConnection.set_connect_state()
1085
1086 self._handshakeInMemory(clientConnection, serverConnection)
1087
1088 self.assertIdentical(verify.connection, clientConnection)
1089
1090
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001091 def test_set_verify_callback_exception(self):
1092 """
1093 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1094 exception, verification fails and the exception is propagated to the
1095 caller of :py:obj:`Connection.do_handshake`.
1096 """
1097 serverContext = Context(TLSv1_METHOD)
1098 serverContext.use_privatekey(
1099 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1100 serverContext.use_certificate(
1101 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1102
1103 clientContext = Context(TLSv1_METHOD)
1104 def verify_callback(*args):
1105 raise Exception("silly verify failure")
1106 clientContext.set_verify(VERIFY_PEER, verify_callback)
1107
1108 exc = self.assertRaises(
1109 Exception, self._handshake_test, serverContext, clientContext)
1110 self.assertEqual("silly verify failure", str(exc))
1111
1112
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001113 def test_add_extra_chain_cert(self):
1114 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001115 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509` instance to add to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001116 the certificate chain.
1117
Jonathan Ballet648875f2011-07-16 14:14:58 +09001118 See :py:obj:`_create_certificate_chain` for the details of the certificate
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001119 chain tested.
1120
1121 The chain is tested by starting a server with scert and connecting
1122 to it with a client which trusts cacert and requires verification to
1123 succeed.
1124 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001125 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001126 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1127
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001128 # Dump the CA certificate to a file because that's the only way to load
1129 # it as a trusted CA in the client context.
1130 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001131 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001132 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001133 fObj.close()
1134
1135 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001136 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001137 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001138 fObj.close()
1139
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001140 # Create the server context
1141 serverContext = Context(TLSv1_METHOD)
1142 serverContext.use_privatekey(skey)
1143 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001144 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001145 serverContext.add_extra_chain_cert(icert)
1146
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001147 # Create the client
1148 clientContext = Context(TLSv1_METHOD)
1149 clientContext.set_verify(
1150 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001151 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001152
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001153 # Try it out.
1154 self._handshake_test(serverContext, clientContext)
1155
1156
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001157 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001158 """
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001159 Verify that :py:obj:`Context.use_certificate_chain_file` reads a
1160 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001161
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001162 The chain is tested by starting a server with scert and connecting to
1163 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001164 succeed.
1165 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001166 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001167 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1168
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001169 makedirs(certdir)
1170
1171 if isinstance(certdir, binary_type):
1172 chainFile = join(certdir, b("chain.pem"))
1173 caFile = join(certdir, b("ca.pem"))
1174 else:
1175 chainFile = join(certdir, u"chain.pem")
1176 caFile = join(certdir, u"ca.pem")
1177
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001178 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001179 with open(chainFile, 'wb') as fObj:
1180 # Most specific to least general.
1181 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1182 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1183 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1184
1185 with open(caFile, 'w') as fObj:
1186 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001187
1188 serverContext = Context(TLSv1_METHOD)
1189 serverContext.use_certificate_chain_file(chainFile)
1190 serverContext.use_privatekey(skey)
1191
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001192 clientContext = Context(TLSv1_METHOD)
1193 clientContext.set_verify(
1194 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001195 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001196
1197 self._handshake_test(serverContext, clientContext)
1198
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001199
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001200 def test_use_certificate_chain_file_bytes(self):
1201 """
1202 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1203 an instance of ``bytes``) to specify additional certificates to use to
1204 construct and verify a trust chain.
1205 """
1206 self._use_certificate_chain_file_test(
1207 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
1208 )
1209
1210
1211 def test_use_certificate_chain_file_unicode(self):
1212 """
1213 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1214 an instance of ``unicode``) to specify additional certificates to use
1215 to construct and verify a trust chain.
1216 """
1217 self._use_certificate_chain_file_test(
1218 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
1219 )
1220
1221
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001222 def test_use_certificate_chain_file_wrong_args(self):
1223 """
1224 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1225 if passed zero or more than one argument or when passed a non-byte
1226 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error` when
1227 passed a bad chain file name (for example, the name of a file which does
1228 not exist).
1229 """
1230 context = Context(TLSv1_METHOD)
1231 self.assertRaises(TypeError, context.use_certificate_chain_file)
1232 self.assertRaises(TypeError, context.use_certificate_chain_file, object())
1233 self.assertRaises(TypeError, context.use_certificate_chain_file, b"foo", object())
1234
1235 self.assertRaises(Error, context.use_certificate_chain_file, self.mktemp())
1236
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001237 # XXX load_client_ca
1238 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001239
1240 def test_get_verify_mode_wrong_args(self):
1241 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001242 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001243 arguments.
1244 """
1245 context = Context(TLSv1_METHOD)
1246 self.assertRaises(TypeError, context.get_verify_mode, None)
1247
1248
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001249 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001250 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001251 :py:obj:`Context.get_verify_mode` returns the verify mode flags previously
1252 passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001253 """
1254 context = Context(TLSv1_METHOD)
1255 self.assertEquals(context.get_verify_mode(), 0)
1256 context.set_verify(
1257 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1258 self.assertEquals(
1259 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1260
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001261
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001262 if not PY3:
1263 def test_set_verify_mode_long(self):
1264 """
1265 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1266 type :py:obj:`long` as well as :py:obj:`int`.
1267 """
1268 context = Context(TLSv1_METHOD)
1269 self.assertEquals(context.get_verify_mode(), 0)
1270 context.set_verify(
1271 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None)
1272 self.assertEquals(
1273 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1274
1275
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001276 def test_load_tmp_dh_wrong_args(self):
1277 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001278 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
1279 number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001280 """
1281 context = Context(TLSv1_METHOD)
1282 self.assertRaises(TypeError, context.load_tmp_dh)
1283 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1284 self.assertRaises(TypeError, context.load_tmp_dh, object())
1285
1286
1287 def test_load_tmp_dh_missing_file(self):
1288 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001289 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the specified file
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001290 does not exist.
1291 """
1292 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001293 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001294
1295
1296 def test_load_tmp_dh(self):
1297 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001298 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001299 specified file.
1300 """
1301 context = Context(TLSv1_METHOD)
1302 dhfilename = self.mktemp()
1303 dhfile = open(dhfilename, "w")
1304 dhfile.write(dhparam)
1305 dhfile.close()
1306 context.load_tmp_dh(dhfilename)
1307 # XXX What should I assert here? -exarkun
1308
1309
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001310 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001311 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001312 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001313 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001314 """
1315 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001316 for curve in get_elliptic_curves():
1317 # The only easily "assertable" thing is that it does not raise an
1318 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001319 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001320
1321
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001322 def test_set_cipher_list_bytes(self):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001323 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001324 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
1325 ciphers which connections created with the context object will be able
1326 to choose from.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001327 """
1328 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001329 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001330 conn = Connection(context, None)
1331 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001332
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001333
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001334 def test_set_cipher_list_text(self):
1335 """
1336 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
1337 the ciphers which connections created with the context object will be
1338 able to choose from.
1339 """
1340 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -05001341 context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001342 conn = Connection(context, None)
1343 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
1344
1345
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001346 def test_set_cipher_list_wrong_args(self):
1347 """
Jean-Paul Calderone17044832014-01-18 10:20:11 -05001348 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
1349 passed zero arguments or more than one argument or when passed a
1350 non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001351 passed an incorrect cipher list string.
1352 """
1353 context = Context(TLSv1_METHOD)
1354 self.assertRaises(TypeError, context.set_cipher_list)
1355 self.assertRaises(TypeError, context.set_cipher_list, object())
1356 self.assertRaises(TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object())
1357
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001358 self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001359
1360
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001361 def test_set_session_cache_mode_wrong_args(self):
1362 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001363 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1364 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001365 """
1366 context = Context(TLSv1_METHOD)
1367 self.assertRaises(TypeError, context.set_session_cache_mode)
1368 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1369
1370
1371 def test_get_session_cache_mode_wrong_args(self):
1372 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001373 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1374 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001375 """
1376 context = Context(TLSv1_METHOD)
1377 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1378
1379
1380 def test_session_cache_mode(self):
1381 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001382 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1383 cached. The setting can be retrieved via
1384 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001385 """
1386 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001387 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001388 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1389 self.assertEqual(SESS_CACHE_OFF, off)
1390 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1391
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001392 if not PY3:
1393 def test_session_cache_mode_long(self):
1394 """
1395 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1396 of type :py:obj:`long` as well as :py:obj:`int`.
1397 """
1398 context = Context(TLSv1_METHOD)
1399 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1400 self.assertEqual(
1401 SESS_CACHE_BOTH, context.get_session_cache_mode())
1402
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001403
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001404 def test_get_cert_store(self):
1405 """
1406 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store` instance.
1407 """
1408 context = Context(TLSv1_METHOD)
1409 store = context.get_cert_store()
1410 self.assertIsInstance(store, X509Store)
1411
1412
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001413
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001414class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1415 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001416 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
1417 :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001418 """
1419 def test_wrong_args(self):
1420 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001421 :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001422 with other than one argument.
1423 """
1424 context = Context(TLSv1_METHOD)
1425 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1426 self.assertRaises(
1427 TypeError, context.set_tlsext_servername_callback, 1, 2)
1428
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001429
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001430 def test_old_callback_forgotten(self):
1431 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001432 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001433 callback, the one it replaces is dereferenced.
1434 """
1435 def callback(connection):
1436 pass
1437
1438 def replacement(connection):
1439 pass
1440
1441 context = Context(TLSv1_METHOD)
1442 context.set_tlsext_servername_callback(callback)
1443
1444 tracker = ref(callback)
1445 del callback
1446
1447 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001448
1449 # One run of the garbage collector happens to work on CPython. PyPy
1450 # doesn't collect the underlying object until a second run for whatever
1451 # reason. That's fine, it still demonstrates our code has properly
1452 # dropped the reference.
1453 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001454 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001455
1456 callback = tracker()
1457 if callback is not None:
1458 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001459 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001460 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001461
1462
1463 def test_no_servername(self):
1464 """
1465 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001466 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
1467 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001468 """
1469 args = []
1470 def servername(conn):
1471 args.append((conn, conn.get_servername()))
1472 context = Context(TLSv1_METHOD)
1473 context.set_tlsext_servername_callback(servername)
1474
1475 # Lose our reference to it. The Context is responsible for keeping it
1476 # alive now.
1477 del servername
1478 collect()
1479
1480 # Necessary to actually accept the connection
1481 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1482 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1483
1484 # Do a little connection to trigger the logic
1485 server = Connection(context, None)
1486 server.set_accept_state()
1487
1488 client = Connection(Context(TLSv1_METHOD), None)
1489 client.set_connect_state()
1490
1491 self._interactInMemory(server, client)
1492
1493 self.assertEqual([(server, None)], args)
1494
1495
1496 def test_servername(self):
1497 """
1498 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +09001499 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
1500 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001501 """
1502 args = []
1503 def servername(conn):
1504 args.append((conn, conn.get_servername()))
1505 context = Context(TLSv1_METHOD)
1506 context.set_tlsext_servername_callback(servername)
1507
1508 # Necessary to actually accept the connection
1509 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1510 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1511
1512 # Do a little connection to trigger the logic
1513 server = Connection(context, None)
1514 server.set_accept_state()
1515
1516 client = Connection(Context(TLSv1_METHOD), None)
1517 client.set_connect_state()
1518 client.set_tlsext_host_name(b("foo1.example.com"))
1519
1520 self._interactInMemory(server, client)
1521
1522 self.assertEqual([(server, b("foo1.example.com"))], args)
1523
1524
1525
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001526class SessionTests(TestCase):
1527 """
1528 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1529 """
1530 def test_construction(self):
1531 """
1532 :py:class:`Session` can be constructed with no arguments, creating a new
1533 instance of that type.
1534 """
1535 new_session = Session()
1536 self.assertTrue(isinstance(new_session, Session))
1537
1538
1539 def test_construction_wrong_args(self):
1540 """
1541 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
1542 is raised.
1543 """
1544 self.assertRaises(TypeError, Session, 123)
1545 self.assertRaises(TypeError, Session, "hello")
1546 self.assertRaises(TypeError, Session, object())
1547
1548
1549
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001550class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05001551 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001552 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001553 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001554 # XXX get_peer_certificate -> None
1555 # XXX sock_shutdown
1556 # XXX master_key -> TypeError
1557 # XXX server_random -> TypeError
1558 # XXX state_string
1559 # XXX connect -> TypeError
1560 # XXX connect_ex -> TypeError
1561 # XXX set_connect_state -> TypeError
1562 # XXX set_accept_state -> TypeError
1563 # XXX renegotiate_pending
1564 # XXX do_handshake -> TypeError
1565 # XXX bio_read -> TypeError
1566 # XXX recv -> TypeError
1567 # XXX send -> TypeError
1568 # XXX bio_write -> TypeError
1569
Rick Deane15b1472009-07-09 15:53:42 -05001570 def test_type(self):
1571 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001572 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001573 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05001574 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001575 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05001576 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001577 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05001578
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001579
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001580 def test_get_context(self):
1581 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001582 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
1583 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001584 """
1585 context = Context(TLSv1_METHOD)
1586 connection = Connection(context, None)
1587 self.assertIdentical(connection.get_context(), context)
1588
1589
1590 def test_get_context_wrong_args(self):
1591 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001592 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001593 arguments.
1594 """
1595 connection = Connection(Context(TLSv1_METHOD), None)
1596 self.assertRaises(TypeError, connection.get_context, None)
1597
1598
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001599 def test_set_context_wrong_args(self):
1600 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001601 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
1602 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001603 than 1.
1604 """
1605 ctx = Context(TLSv1_METHOD)
1606 connection = Connection(ctx, None)
1607 self.assertRaises(TypeError, connection.set_context)
1608 self.assertRaises(TypeError, connection.set_context, object())
1609 self.assertRaises(TypeError, connection.set_context, "hello")
1610 self.assertRaises(TypeError, connection.set_context, 1)
1611 self.assertRaises(TypeError, connection.set_context, 1, 2)
1612 self.assertRaises(
1613 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
1614 self.assertIdentical(ctx, connection.get_context())
1615
1616
1617 def test_set_context(self):
1618 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001619 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001620 for the connection.
1621 """
1622 original = Context(SSLv23_METHOD)
1623 replacement = Context(TLSv1_METHOD)
1624 connection = Connection(original, None)
1625 connection.set_context(replacement)
1626 self.assertIdentical(replacement, connection.get_context())
1627 # Lose our references to the contexts, just in case the Connection isn't
1628 # properly managing its own contributions to their reference counts.
1629 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001630 collect()
1631
1632
1633 def test_set_tlsext_host_name_wrong_args(self):
1634 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001635 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001636 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09001637 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001638 """
1639 conn = Connection(Context(TLSv1_METHOD), None)
1640 self.assertRaises(TypeError, conn.set_tlsext_host_name)
1641 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
1642 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
1643 self.assertRaises(
1644 TypeError, conn.set_tlsext_host_name, b("with\0null"))
1645
1646 if version_info >= (3,):
1647 # On Python 3.x, don't accidentally implicitly convert from text.
1648 self.assertRaises(
1649 TypeError,
1650 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001651
1652
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001653 def test_get_servername_wrong_args(self):
1654 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001655 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001656 arguments.
1657 """
1658 connection = Connection(Context(TLSv1_METHOD), None)
1659 self.assertRaises(TypeError, connection.get_servername, object())
1660 self.assertRaises(TypeError, connection.get_servername, 1)
1661 self.assertRaises(TypeError, connection.get_servername, "hello")
1662
1663
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001664 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001665 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001666 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001667 immediate read.
1668 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001669 connection = Connection(Context(TLSv1_METHOD), None)
1670 self.assertEquals(connection.pending(), 0)
1671
1672
1673 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001674 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001675 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001676 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001677 connection = Connection(Context(TLSv1_METHOD), None)
1678 self.assertRaises(TypeError, connection.pending, None)
1679
1680
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001681 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001682 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001683 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001684 argument or with the wrong number of arguments.
1685 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001686 connection = Connection(Context(TLSv1_METHOD), socket())
1687 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001688 self.assertRaises(TypeError, connection.connect)
1689 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001690
1691
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001692 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001693 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001694 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001695 connect method raises it.
1696 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001697 client = socket()
1698 context = Context(TLSv1_METHOD)
1699 clientSSL = Connection(context, client)
1700 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04001701 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001702
1703
1704 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001705 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001706 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001707 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001708 port = socket()
1709 port.bind(('', 0))
1710 port.listen(3)
1711
1712 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001713 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
1714 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001715
1716
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001717 if platform == "darwin":
1718 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
1719 else:
1720 def test_connect_ex(self):
1721 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001722 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001723 errno instead of raising an exception.
1724 """
1725 port = socket()
1726 port.bind(('', 0))
1727 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001728
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001729 clientSSL = Connection(Context(TLSv1_METHOD), socket())
1730 clientSSL.setblocking(False)
1731 result = clientSSL.connect_ex(port.getsockname())
1732 expected = (EINPROGRESS, EWOULDBLOCK)
1733 self.assertTrue(
1734 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001735
1736
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001737 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001738 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001739 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001740 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001741 connection = Connection(Context(TLSv1_METHOD), socket())
1742 self.assertRaises(TypeError, connection.accept, None)
1743
1744
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001745 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001746 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001747 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
1748 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001749 connection originated from.
1750 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001751 ctx = Context(TLSv1_METHOD)
1752 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1753 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001754 port = socket()
1755 portSSL = Connection(ctx, port)
1756 portSSL.bind(('', 0))
1757 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001758
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001759 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001760
1761 # Calling portSSL.getsockname() here to get the server IP address sounds
1762 # great, but frequently fails on Windows.
1763 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001764
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001765 serverSSL, address = portSSL.accept()
1766
1767 self.assertTrue(isinstance(serverSSL, Connection))
1768 self.assertIdentical(serverSSL.get_context(), ctx)
1769 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001770
1771
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001772 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001773 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001774 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001775 number of arguments or with arguments other than integers.
1776 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001777 connection = Connection(Context(TLSv1_METHOD), None)
1778 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04001779 self.assertRaises(TypeError, connection.get_shutdown, None)
1780 self.assertRaises(TypeError, connection.set_shutdown)
1781 self.assertRaises(TypeError, connection.set_shutdown, None)
1782 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001783
1784
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001785 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001786 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001787 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001788 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001789 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001790 self.assertFalse(server.shutdown())
1791 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001792 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001793 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
1794 client.shutdown()
1795 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
1796 self.assertRaises(ZeroReturnError, server.recv, 1024)
1797 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001798
1799
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001800 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001801 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001802 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001803 process.
1804 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001805 connection = Connection(Context(TLSv1_METHOD), socket())
1806 connection.set_shutdown(RECEIVED_SHUTDOWN)
1807 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1808
1809
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05001810 if not PY3:
1811 def test_set_shutdown_long(self):
1812 """
1813 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
1814 of type :py:obj:`long` as well as :py:obj:`int`.
1815 """
1816 connection = Connection(Context(TLSv1_METHOD), socket())
1817 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
1818 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1819
1820
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001821 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001822 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001823 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
1824 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001825 with any arguments.
1826 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001827 conn = Connection(Context(TLSv1_METHOD), None)
1828 self.assertRaises(TypeError, conn.get_app_data, None)
1829 self.assertRaises(TypeError, conn.set_app_data)
1830 self.assertRaises(TypeError, conn.set_app_data, None, None)
1831
1832
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001833 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001834 """
1835 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001836 :py:obj:`Connection.set_app_data` and later retrieved with
1837 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001838 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001839 conn = Connection(Context(TLSv1_METHOD), None)
1840 app_data = object()
1841 conn.set_app_data(app_data)
1842 self.assertIdentical(conn.get_app_data(), app_data)
1843
1844
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001845 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001846 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001847 :py:obj:`Connection.makefile` is not implemented and calling that method raises
1848 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001849 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001850 conn = Connection(Context(TLSv1_METHOD), None)
1851 self.assertRaises(NotImplementedError, conn.makefile)
1852
1853
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001854 def test_get_peer_cert_chain_wrong_args(self):
1855 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001856 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001857 arguments.
1858 """
1859 conn = Connection(Context(TLSv1_METHOD), None)
1860 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
1861 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
1862 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
1863 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
1864
1865
1866 def test_get_peer_cert_chain(self):
1867 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001868 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001869 the connected server returned for the certification verification.
1870 """
1871 chain = _create_certificate_chain()
1872 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1873
1874 serverContext = Context(TLSv1_METHOD)
1875 serverContext.use_privatekey(skey)
1876 serverContext.use_certificate(scert)
1877 serverContext.add_extra_chain_cert(icert)
1878 serverContext.add_extra_chain_cert(cacert)
1879 server = Connection(serverContext, None)
1880 server.set_accept_state()
1881
1882 # Create the client
1883 clientContext = Context(TLSv1_METHOD)
1884 clientContext.set_verify(VERIFY_NONE, verify_cb)
1885 client = Connection(clientContext, None)
1886 client.set_connect_state()
1887
1888 self._interactInMemory(client, server)
1889
1890 chain = client.get_peer_cert_chain()
1891 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001892 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001893 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001894 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001895 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001896 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001897 "Authority Certificate", chain[2].get_subject().CN)
1898
1899
1900 def test_get_peer_cert_chain_none(self):
1901 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001902 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001903 certificate chain.
1904 """
1905 ctx = Context(TLSv1_METHOD)
1906 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1907 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1908 server = Connection(ctx, None)
1909 server.set_accept_state()
1910 client = Connection(Context(TLSv1_METHOD), None)
1911 client.set_connect_state()
1912 self._interactInMemory(client, server)
1913 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001914
1915
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001916 def test_get_session_wrong_args(self):
1917 """
1918 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
1919 with any arguments.
1920 """
1921 ctx = Context(TLSv1_METHOD)
1922 server = Connection(ctx, None)
1923 self.assertRaises(TypeError, server.get_session, 123)
1924 self.assertRaises(TypeError, server.get_session, "hello")
1925 self.assertRaises(TypeError, server.get_session, object())
1926
1927
1928 def test_get_session_unconnected(self):
1929 """
1930 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
1931 an object which has not been connected.
1932 """
1933 ctx = Context(TLSv1_METHOD)
1934 server = Connection(ctx, None)
1935 session = server.get_session()
1936 self.assertIdentical(None, session)
1937
1938
1939 def test_server_get_session(self):
1940 """
1941 On the server side of a connection, :py:obj:`Connection.get_session`
1942 returns a :py:class:`Session` instance representing the SSL session for
1943 that connection.
1944 """
1945 server, client = self._loopback()
1946 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001947 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001948
1949
1950 def test_client_get_session(self):
1951 """
1952 On the client side of a connection, :py:obj:`Connection.get_session`
1953 returns a :py:class:`Session` instance representing the SSL session for
1954 that connection.
1955 """
1956 server, client = self._loopback()
1957 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001958 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001959
1960
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05001961 def test_set_session_wrong_args(self):
1962 """
1963 If called with an object that is not an instance of :py:class:`Session`,
1964 or with other than one argument, :py:obj:`Connection.set_session` raises
1965 :py:obj:`TypeError`.
1966 """
1967 ctx = Context(TLSv1_METHOD)
1968 connection = Connection(ctx, None)
1969 self.assertRaises(TypeError, connection.set_session)
1970 self.assertRaises(TypeError, connection.set_session, 123)
1971 self.assertRaises(TypeError, connection.set_session, "hello")
1972 self.assertRaises(TypeError, connection.set_session, object())
1973 self.assertRaises(
1974 TypeError, connection.set_session, Session(), Session())
1975
1976
1977 def test_client_set_session(self):
1978 """
1979 :py:obj:`Connection.set_session`, when used prior to a connection being
1980 established, accepts a :py:class:`Session` instance and causes an
1981 attempt to re-use the session it represents when the SSL handshake is
1982 performed.
1983 """
1984 key = load_privatekey(FILETYPE_PEM, server_key_pem)
1985 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
1986 ctx = Context(TLSv1_METHOD)
1987 ctx.use_privatekey(key)
1988 ctx.use_certificate(cert)
1989 ctx.set_session_id("unity-test")
1990
1991 def makeServer(socket):
1992 server = Connection(ctx, socket)
1993 server.set_accept_state()
1994 return server
1995
1996 originalServer, originalClient = self._loopback(
1997 serverFactory=makeServer)
1998 originalSession = originalClient.get_session()
1999
2000 def makeClient(socket):
2001 client = self._loopbackClientFactory(socket)
2002 client.set_session(originalSession)
2003 return client
2004 resumedServer, resumedClient = self._loopback(
2005 serverFactory=makeServer,
2006 clientFactory=makeClient)
2007
2008 # This is a proxy: in general, we have no access to any unique
2009 # identifier for the session (new enough versions of OpenSSL expose a
2010 # hash which could be usable, but "new enough" is very, very new).
2011 # Instead, exploit the fact that the master key is re-used if the
2012 # session is re-used. As long as the master key for the two connections
2013 # is the same, the session was re-used!
2014 self.assertEqual(
2015 originalServer.master_key(), resumedServer.master_key())
2016
2017
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002018 def test_set_session_wrong_method(self):
2019 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002020 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
2021 instance associated with a context using a different SSL method than the
2022 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
2023 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002024 """
2025 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2026 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2027 ctx = Context(TLSv1_METHOD)
2028 ctx.use_privatekey(key)
2029 ctx.use_certificate(cert)
2030 ctx.set_session_id("unity-test")
2031
2032 def makeServer(socket):
2033 server = Connection(ctx, socket)
2034 server.set_accept_state()
2035 return server
2036
2037 originalServer, originalClient = self._loopback(
2038 serverFactory=makeServer)
2039 originalSession = originalClient.get_session()
2040
2041 def makeClient(socket):
2042 # Intentionally use a different, incompatible method here.
2043 client = Connection(Context(SSLv3_METHOD), socket)
2044 client.set_connect_state()
2045 client.set_session(originalSession)
2046 return client
2047
2048 self.assertRaises(
2049 Error,
2050 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2051
2052
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002053 def test_wantWriteError(self):
2054 """
2055 :py:obj:`Connection` methods which generate output raise
2056 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2057 fail indicating a should-write state.
2058 """
2059 client_socket, server_socket = socket_pair()
2060 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002061 # anything. Only write a single byte at a time so we can be sure we
2062 # completely fill the buffer. Even though the socket API is allowed to
2063 # signal a short write via its return value it seems this doesn't
2064 # always happen on all platforms (FreeBSD and OS X particular) for the
2065 # very last bit of available buffer space.
2066 msg = b"x"
2067 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002068 try:
2069 client_socket.send(msg)
2070 except error as e:
2071 if e.errno == EWOULDBLOCK:
2072 break
2073 raise
2074 else:
2075 self.fail(
2076 "Failed to fill socket buffer, cannot test BIO want write")
2077
2078 ctx = Context(TLSv1_METHOD)
2079 conn = Connection(ctx, client_socket)
2080 # Client's speak first, so make it an SSL client
2081 conn.set_connect_state()
2082 self.assertRaises(WantWriteError, conn.do_handshake)
2083
2084 # XXX want_read
2085
Fedor Brunner416f4a12014-03-28 13:18:38 +01002086 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002087 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002088 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2089 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002090 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002091 ctx = Context(TLSv1_METHOD)
2092 connection = Connection(ctx, None)
2093 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002094
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002095
Fedor Brunner416f4a12014-03-28 13:18:38 +01002096 def test_get_peer_finished_before_connect(self):
2097 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002098 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2099 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002100 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002101 ctx = Context(TLSv1_METHOD)
2102 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002103 self.assertEqual(connection.get_peer_finished(), None)
2104
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002105
Fedor Brunner416f4a12014-03-28 13:18:38 +01002106 def test_get_finished(self):
2107 """
2108 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002109 message send from client, or server. Finished messages are send during
2110 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002111 """
2112
Fedor Brunner5747b932014-03-05 14:22:34 +01002113 server, client = self._loopback()
2114
2115 self.assertNotEqual(server.get_finished(), None)
2116 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002117
Jean-Paul Calderoned979f232014-03-30 11:58:00 -04002118
Fedor Brunner416f4a12014-03-28 13:18:38 +01002119 def test_get_peer_finished(self):
2120 """
2121 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002122 message received from client, or server. Finished messages are send
2123 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002124 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002125 server, client = self._loopback()
2126
2127 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002128 self.assertTrue(len(server.get_peer_finished()) > 0)
2129
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002130
Fedor Brunner416f4a12014-03-28 13:18:38 +01002131 def test_tls_finished_message_symmetry(self):
2132 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002133 The TLS Finished message send by server must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002134 received by client.
2135
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002136 The TLS Finished message send by client must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002137 received by server.
2138 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002139 server, client = self._loopback()
2140
Fedor Brunner5747b932014-03-05 14:22:34 +01002141 self.assertEqual(server.get_finished(), client.get_peer_finished())
2142 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002143
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002144
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002145 def test_get_cipher_name_before_connect(self):
2146 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002147 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2148 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002149 """
2150 ctx = Context(TLSv1_METHOD)
2151 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002152 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002153
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002154
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002155 def test_get_cipher_name(self):
2156 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002157 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2158 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002159 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002160 server, client = self._loopback()
2161 server_cipher_name, client_cipher_name = \
2162 server.get_cipher_name(), client.get_cipher_name()
2163
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002164 self.assertIsInstance(server_cipher_name, text_type)
2165 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002166
2167 self.assertEqual(server_cipher_name, client_cipher_name)
2168
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002169
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002170 def test_get_cipher_version_before_connect(self):
2171 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002172 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2173 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002174 """
2175 ctx = Context(TLSv1_METHOD)
2176 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002177 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002178
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002179
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002180 def test_get_cipher_version(self):
2181 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002182 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2183 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002184 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002185 server, client = self._loopback()
2186 server_cipher_version, client_cipher_version = \
2187 server.get_cipher_version(), client.get_cipher_version()
2188
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002189 self.assertIsInstance(server_cipher_version, text_type)
2190 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002191
2192 self.assertEqual(server_cipher_version, client_cipher_version)
2193
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002194
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002195 def test_get_cipher_bits_before_connect(self):
2196 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002197 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2198 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002199 """
2200 ctx = Context(TLSv1_METHOD)
2201 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002202 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002203
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002204
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002205 def test_get_cipher_bits(self):
2206 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002207 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2208 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002209 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002210 server, client = self._loopback()
2211 server_cipher_bits, client_cipher_bits = \
2212 server.get_cipher_bits(), client.get_cipher_bits()
2213
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002214 self.assertIsInstance(server_cipher_bits, int)
2215 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002216
2217 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002218
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002219
2220
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002221class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002222 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002223 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002224 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002225 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002226 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002227 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002228 arguments.
2229 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002230 connection = Connection(Context(TLSv1_METHOD), None)
2231 self.assertRaises(TypeError, connection.get_cipher_list, None)
2232
2233
2234 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002235 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002236 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2237 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002238 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002239 connection = Connection(Context(TLSv1_METHOD), None)
2240 ciphers = connection.get_cipher_list()
2241 self.assertTrue(isinstance(ciphers, list))
2242 for cipher in ciphers:
2243 self.assertTrue(isinstance(cipher, str))
2244
2245
2246
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002247class ConnectionSendTests(TestCase, _LoopbackMixin):
2248 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002249 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002250 """
2251 def test_wrong_args(self):
2252 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002253 When called with arguments other than string argument for its first
2254 parameter or more than two arguments, :py:obj:`Connection.send` raises
2255 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002256 """
2257 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002258 self.assertRaises(TypeError, connection.send)
2259 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002260 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002261
2262
2263 def test_short_bytes(self):
2264 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002265 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002266 and returns the number of bytes sent.
2267 """
2268 server, client = self._loopback()
2269 count = server.send(b('xy'))
2270 self.assertEquals(count, 2)
2271 self.assertEquals(client.recv(2), b('xy'))
2272
2273 try:
2274 memoryview
2275 except NameError:
2276 "cannot test sending memoryview without memoryview"
2277 else:
2278 def test_short_memoryview(self):
2279 """
2280 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002281 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002282 bytes sent.
2283 """
2284 server, client = self._loopback()
2285 count = server.send(memoryview(b('xy')))
2286 self.assertEquals(count, 2)
2287 self.assertEquals(client.recv(2), b('xy'))
2288
2289
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002290 try:
2291 buffer
2292 except NameError:
2293 "cannot test sending buffer without buffer"
2294 else:
2295 def test_short_buffer(self):
2296 """
2297 When passed a buffer containing a small number of bytes,
2298 :py:obj:`Connection.send` transmits all of them and returns the number of
2299 bytes sent.
2300 """
2301 server, client = self._loopback()
2302 count = server.send(buffer(b('xy')))
2303 self.assertEquals(count, 2)
2304 self.assertEquals(client.recv(2), b('xy'))
2305
2306
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002307
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002308class ConnectionSendallTests(TestCase, _LoopbackMixin):
2309 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002310 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002311 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002312 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002313 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002314 When called with arguments other than a string argument for its first
2315 parameter or with more than two arguments, :py:obj:`Connection.sendall`
2316 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002317 """
2318 connection = Connection(Context(TLSv1_METHOD), None)
2319 self.assertRaises(TypeError, connection.sendall)
2320 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002321 self.assertRaises(
2322 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002323
2324
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002325 def test_short(self):
2326 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002327 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002328 it.
2329 """
2330 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04002331 server.sendall(b('x'))
2332 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002333
2334
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002335 try:
2336 memoryview
2337 except NameError:
2338 "cannot test sending memoryview without memoryview"
2339 else:
2340 def test_short_memoryview(self):
2341 """
2342 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002343 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002344 """
2345 server, client = self._loopback()
2346 server.sendall(memoryview(b('x')))
2347 self.assertEquals(client.recv(1), b('x'))
2348
2349
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002350 try:
2351 buffer
2352 except NameError:
2353 "cannot test sending buffers without buffers"
2354 else:
2355 def test_short_buffers(self):
2356 """
2357 When passed a buffer containing a small number of bytes,
2358 :py:obj:`Connection.sendall` transmits all of them.
2359 """
2360 server, client = self._loopback()
2361 server.sendall(buffer(b('x')))
2362 self.assertEquals(client.recv(1), b('x'))
2363
2364
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002365 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002366 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002367 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002368 it even if this requires multiple calls of an underlying write function.
2369 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002370 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04002371 # Should be enough, underlying SSL_write should only do 16k at a time.
2372 # On Windows, after 32k of bytes the write will block (forever - because
2373 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04002374 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002375 server.sendall(message)
2376 accum = []
2377 received = 0
2378 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04002379 data = client.recv(1024)
2380 accum.append(data)
2381 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04002382 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002383
2384
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002385 def test_closed(self):
2386 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002387 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002388 write error from the low level write call.
2389 """
2390 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04002391 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002392 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02002393 if platform == "win32":
2394 self.assertEqual(exc.args[0], ESHUTDOWN)
2395 else:
2396 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002397
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002398
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002399
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002400class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
2401 """
2402 Tests for SSL renegotiation APIs.
2403 """
2404 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002405 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002406 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002407 arguments.
2408 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002409 connection = Connection(Context(TLSv1_METHOD), None)
2410 self.assertRaises(TypeError, connection.renegotiate, None)
2411
2412
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002413 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002414 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002415 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002416 any arguments.
2417 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002418 connection = Connection(Context(TLSv1_METHOD), None)
2419 self.assertRaises(TypeError, connection.total_renegotiations, None)
2420
2421
2422 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002423 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002424 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002425 renegotiations have happened.
2426 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002427 connection = Connection(Context(TLSv1_METHOD), None)
2428 self.assertEquals(connection.total_renegotiations(), 0)
2429
2430
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002431# def test_renegotiate(self):
2432# """
2433# """
2434# server, client = self._loopback()
2435
2436# server.send("hello world")
2437# self.assertEquals(client.recv(len("hello world")), "hello world")
2438
2439# self.assertEquals(server.total_renegotiations(), 0)
2440# self.assertTrue(server.renegotiate())
2441
2442# server.setblocking(False)
2443# client.setblocking(False)
2444# while server.renegotiate_pending():
2445# client.do_handshake()
2446# server.do_handshake()
2447
2448# self.assertEquals(server.total_renegotiations(), 1)
2449
2450
2451
2452
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002453class ErrorTests(TestCase):
2454 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002455 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002456 """
2457 def test_type(self):
2458 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002459 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002460 """
2461 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05002462 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05002463
2464
2465
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002466class ConstantsTests(TestCase):
2467 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002468 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002469
2470 These are values defined by OpenSSL intended only to be used as flags to
2471 OpenSSL APIs. The only assertions it seems can be made about them is
2472 their values.
2473 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002474 # unittest.TestCase has no skip mechanism
2475 if OP_NO_QUERY_MTU is not None:
2476 def test_op_no_query_mtu(self):
2477 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002478 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002479 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002480 """
2481 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
2482 else:
2483 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002484
2485
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002486 if OP_COOKIE_EXCHANGE is not None:
2487 def test_op_cookie_exchange(self):
2488 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002489 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002490 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002491 """
2492 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
2493 else:
2494 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002495
2496
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002497 if OP_NO_TICKET is not None:
2498 def test_op_no_ticket(self):
2499 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002500 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002501 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002502 """
2503 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04002504 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002505 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05002506
2507
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002508 if OP_NO_COMPRESSION is not None:
2509 def test_op_no_compression(self):
2510 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002511 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
2512 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002513 """
2514 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
2515 else:
2516 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
2517
2518
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002519 def test_sess_cache_off(self):
2520 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002521 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
2522 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002523 """
2524 self.assertEqual(0x0, SESS_CACHE_OFF)
2525
2526
2527 def test_sess_cache_client(self):
2528 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002529 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
2530 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002531 """
2532 self.assertEqual(0x1, SESS_CACHE_CLIENT)
2533
2534
2535 def test_sess_cache_server(self):
2536 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002537 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
2538 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002539 """
2540 self.assertEqual(0x2, SESS_CACHE_SERVER)
2541
2542
2543 def test_sess_cache_both(self):
2544 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002545 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
2546 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002547 """
2548 self.assertEqual(0x3, SESS_CACHE_BOTH)
2549
2550
2551 def test_sess_cache_no_auto_clear(self):
2552 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002553 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
2554 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
2555 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002556 """
2557 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
2558
2559
2560 def test_sess_cache_no_internal_lookup(self):
2561 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002562 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
2563 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
2564 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002565 """
2566 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
2567
2568
2569 def test_sess_cache_no_internal_store(self):
2570 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002571 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
2572 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
2573 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002574 """
2575 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
2576
2577
2578 def test_sess_cache_no_internal(self):
2579 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002580 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
2581 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
2582 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002583 """
2584 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
2585
2586
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04002587
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002588class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05002589 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002590 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05002591 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002592 def _server(self, sock):
2593 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002594 Create a new server-side SSL :py:obj:`Connection` object wrapped around
2595 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002596 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002597 # Create the server side Connection. This is mostly setup boilerplate
2598 # - use TLSv1, use a particular certificate, etc.
2599 server_ctx = Context(TLSv1_METHOD)
2600 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2601 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2602 server_store = server_ctx.get_cert_store()
2603 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2604 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2605 server_ctx.check_privatekey()
2606 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002607 # Here the Connection is actually created. If None is passed as the 2nd
2608 # parameter, it indicates a memory BIO should be created.
2609 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002610 server_conn.set_accept_state()
2611 return server_conn
2612
2613
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002614 def _client(self, sock):
2615 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002616 Create a new client-side SSL :py:obj:`Connection` object wrapped around
2617 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002618 """
2619 # Now create the client side Connection. Similar boilerplate to the
2620 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002621 client_ctx = Context(TLSv1_METHOD)
2622 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2623 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2624 client_store = client_ctx.get_cert_store()
2625 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
2626 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
2627 client_ctx.check_privatekey()
2628 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002629 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002630 client_conn.set_connect_state()
2631 return client_conn
2632
2633
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002634 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002635 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002636 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002637 reading from the output of each and writing those bytes to the input of
2638 the other and in this way establish a connection and exchange
2639 application-level bytes with each other.
2640 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002641 server_conn = self._server(None)
2642 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002643
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002644 # There should be no key or nonces yet.
2645 self.assertIdentical(server_conn.master_key(), None)
2646 self.assertIdentical(server_conn.client_random(), None)
2647 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002648
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002649 # First, the handshake needs to happen. We'll deliver bytes back and
2650 # forth between the client and server until neither of them feels like
2651 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002652 self.assertIdentical(
2653 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002654
2655 # Now that the handshake is done, there should be a key and nonces.
2656 self.assertNotIdentical(server_conn.master_key(), None)
2657 self.assertNotIdentical(server_conn.client_random(), None)
2658 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04002659 self.assertEquals(server_conn.client_random(), client_conn.client_random())
2660 self.assertEquals(server_conn.server_random(), client_conn.server_random())
2661 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
2662 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002663
2664 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002665 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05002666
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002667 server_conn.write(important_message)
2668 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002669 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002670 (client_conn, important_message))
2671
2672 client_conn.write(important_message[::-1])
2673 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002674 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002675 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05002676
2677
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002678 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05002679 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002680 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002681
2682 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09002683 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002684 this test fails, there must be a problem outside the memory BIO
2685 code, as no memory BIO is involved here). Even though this isn't a
2686 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05002687 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04002688 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05002689
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002690 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05002691 client_conn.send(important_message)
2692 msg = server_conn.recv(1024)
2693 self.assertEqual(msg, important_message)
2694
2695 # Again in the other direction, just for fun.
2696 important_message = important_message[::-1]
2697 server_conn.send(important_message)
2698 msg = client_conn.recv(1024)
2699 self.assertEqual(msg, important_message)
2700
2701
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04002702 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05002703 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002704 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
2705 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05002706 """
2707 context = Context(SSLv3_METHOD)
2708 client = socket()
2709 clientSSL = Connection(context, client)
2710 self.assertRaises( TypeError, clientSSL.bio_read, 100)
2711 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04002712 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002713
2714
2715 def test_outgoingOverflow(self):
2716 """
2717 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002718 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002719 returned and that many bytes from the beginning of the input can be
2720 read from the other end of the connection.
2721 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002722 server = self._server(None)
2723 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002724
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002725 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002726
2727 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002728 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002729 # Sanity check. We're trying to test what happens when the entire
2730 # input can't be sent. If the entire input was sent, this test is
2731 # meaningless.
2732 self.assertTrue(sent < size)
2733
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002734 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002735 self.assertIdentical(receiver, server)
2736
2737 # We can rely on all of these bytes being received at once because
2738 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
2739 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002740
2741
2742 def test_shutdown(self):
2743 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002744 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
2745 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002746 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002747 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002748 server.bio_shutdown()
2749 e = self.assertRaises(Error, server.recv, 1024)
2750 # We don't want WantReadError or ZeroReturnError or anything - it's a
2751 # handshake failure.
2752 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002753
2754
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002755 def test_unexpectedEndOfFile(self):
2756 """
2757 If the connection is lost before an orderly SSL shutdown occurs,
2758 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
2759 "Unexpected EOF".
2760 """
2761 server_conn, client_conn = self._loopback()
2762 client_conn.sock_shutdown(SHUT_RDWR)
2763 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
2764 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
2765
2766
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002767 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002768 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002769 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 -04002770
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002771 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002772 before the client and server are connected to each other. This
2773 function should specify a list of CAs for the server to send to the
2774 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09002775 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002776 times.
2777 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002778 server = self._server(None)
2779 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002780 self.assertEqual(client.get_client_ca_list(), [])
2781 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002782 ctx = server.get_context()
2783 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002784 self.assertEqual(client.get_client_ca_list(), [])
2785 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002786 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002787 self.assertEqual(client.get_client_ca_list(), expected)
2788 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002789
2790
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002791 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002792 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002793 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002794 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002795 """
2796 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002797 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
2798 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
2799 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002800
2801
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002802 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002803 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002804 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002805 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09002806 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002807 after the connection is set up.
2808 """
2809 def no_ca(ctx):
2810 ctx.set_client_ca_list([])
2811 return []
2812 self._check_client_ca_list(no_ca)
2813
2814
2815 def test_set_one_ca_list(self):
2816 """
2817 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002818 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002819 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002820 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002821 X509Name after the connection is set up.
2822 """
2823 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2824 cadesc = cacert.get_subject()
2825 def single_ca(ctx):
2826 ctx.set_client_ca_list([cadesc])
2827 return [cadesc]
2828 self._check_client_ca_list(single_ca)
2829
2830
2831 def test_set_multiple_ca_list(self):
2832 """
2833 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002834 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002835 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002836 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002837 X509Names after the connection is set up.
2838 """
2839 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2840 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2841
2842 sedesc = secert.get_subject()
2843 cldesc = clcert.get_subject()
2844
2845 def multiple_ca(ctx):
2846 L = [sedesc, cldesc]
2847 ctx.set_client_ca_list(L)
2848 return L
2849 self._check_client_ca_list(multiple_ca)
2850
2851
2852 def test_reset_ca_list(self):
2853 """
2854 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09002855 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002856 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002857 """
2858 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2859 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2860 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2861
2862 cadesc = cacert.get_subject()
2863 sedesc = secert.get_subject()
2864 cldesc = clcert.get_subject()
2865
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002866 def changed_ca(ctx):
2867 ctx.set_client_ca_list([sedesc, cldesc])
2868 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002869 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002870 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002871
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002872
2873 def test_mutated_ca_list(self):
2874 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002875 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002876 afterwards, this does not affect the list of CA names sent to the
2877 client.
2878 """
2879 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2880 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2881
2882 cadesc = cacert.get_subject()
2883 sedesc = secert.get_subject()
2884
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002885 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002886 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002887 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002888 L.append(sedesc)
2889 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002890 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002891
2892
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002893 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002894 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002895 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002896 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002897 """
2898 ctx = Context(TLSv1_METHOD)
2899 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002900 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002901 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002902 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002903
2904
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002905 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002906 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002907 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09002908 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002909 """
2910 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2911 cadesc = cacert.get_subject()
2912 def single_ca(ctx):
2913 ctx.add_client_ca(cacert)
2914 return [cadesc]
2915 self._check_client_ca_list(single_ca)
2916
2917
2918 def test_multiple_add_client_ca(self):
2919 """
2920 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09002921 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002922 """
2923 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2924 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2925
2926 cadesc = cacert.get_subject()
2927 sedesc = secert.get_subject()
2928
2929 def multiple_ca(ctx):
2930 ctx.add_client_ca(cacert)
2931 ctx.add_client_ca(secert)
2932 return [cadesc, sedesc]
2933 self._check_client_ca_list(multiple_ca)
2934
2935
2936 def test_set_and_add_client_ca(self):
2937 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002938 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
2939 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002940 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002941 """
2942 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2943 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2944 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2945
2946 cadesc = cacert.get_subject()
2947 sedesc = secert.get_subject()
2948 cldesc = clcert.get_subject()
2949
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002950 def mixed_set_add_ca(ctx):
2951 ctx.set_client_ca_list([cadesc, sedesc])
2952 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002953 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002954 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002955
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002956
2957 def test_set_after_add_client_ca(self):
2958 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002959 A call to :py:obj:`Context.set_client_ca_list` after a call to
2960 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002961 call with the names specified by the latter cal.
2962 """
2963 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2964 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2965 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2966
2967 cadesc = cacert.get_subject()
2968 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002969
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002970 def set_replaces_add_ca(ctx):
2971 ctx.add_client_ca(clcert)
2972 ctx.set_client_ca_list([cadesc])
2973 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002974 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002975 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002976
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002977
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002978
2979class ConnectionBIOTests(TestCase):
2980 """
2981 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
2982 """
2983 def test_wantReadError(self):
2984 """
2985 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
2986 if there are no bytes available to be read from the BIO.
2987 """
2988 ctx = Context(TLSv1_METHOD)
2989 conn = Connection(ctx, None)
2990 self.assertRaises(WantReadError, conn.bio_read, 1024)
2991
2992
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002993 def test_buffer_size(self):
2994 """
2995 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
2996 number of bytes to read and return.
2997 """
2998 ctx = Context(TLSv1_METHOD)
2999 conn = Connection(ctx, None)
3000 conn.set_connect_state()
3001 try:
3002 conn.do_handshake()
3003 except WantReadError:
3004 pass
3005 data = conn.bio_read(2)
3006 self.assertEqual(2, len(data))
3007
3008
3009 if not PY3:
3010 def test_buffer_size_long(self):
3011 """
3012 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3013 :py:obj:`long` as well as :py:obj:`int`.
3014 """
3015 ctx = Context(TLSv1_METHOD)
3016 conn = Connection(ctx, None)
3017 conn.set_connect_state()
3018 try:
3019 conn.do_handshake()
3020 except WantReadError:
3021 pass
3022 data = conn.bio_read(long(2))
3023 self.assertEqual(2, len(data))
3024
3025
3026
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003027
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003028class InfoConstantTests(TestCase):
3029 """
3030 Tests for assorted constants exposed for use in info callbacks.
3031 """
3032 def test_integers(self):
3033 """
3034 All of the info constants are integers.
3035
3036 This is a very weak test. It would be nice to have one that actually
3037 verifies that as certain info events happen, the value passed to the
3038 info callback matches up with the constant exposed by OpenSSL.SSL.
3039 """
3040 for const in [
3041 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3042 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3043 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3044 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3045 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
3046 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
3047
3048 self.assertTrue(isinstance(const, int))
3049
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003050
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003051if __name__ == '__main__':
3052 main()