blob: 4c2dff5ea06a213bc3931eaded7560a7f8ea157c [file] [log] [blame]
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05001# Copyright (C) Jean-Paul Calderone
2# See LICENSE for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04003
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04004"""
Jonathan Ballet648875f2011-07-16 14:14:58 +09005Unit tests for :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04006"""
7
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05008from gc import collect, get_referrers
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02009from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE, ESHUTDOWN
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040010from sys import platform, version_info
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070011from socket import SHUT_RDWR, error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040012from os import makedirs
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040013from os.path import join
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -040014from unittest import main
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040015from weakref import ref
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050016
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -050017from six import PY3, u
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050018
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040019from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080020from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040021from OpenSSL.crypto import dump_privatekey, load_privatekey
22from OpenSSL.crypto import dump_certificate, load_certificate
23
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040024from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
25from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040026from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040027from OpenSSL.SSL import (
28 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
29 TLSv1_1_METHOD, TLSv1_2_METHOD)
30from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040031from OpenSSL.SSL import (
32 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040033
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040034from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050035 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
36 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
37 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
38
39from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070040 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050041from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070042 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040043
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050044from OpenSSL.test.util import TestCase, b
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040045from OpenSSL.test.test_crypto import (
46 cleartextCertificatePEM, cleartextPrivateKeyPEM)
47from OpenSSL.test.test_crypto import (
48 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
49 root_cert_pem)
50
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050051try:
52 from OpenSSL.SSL import OP_NO_QUERY_MTU
53except ImportError:
54 OP_NO_QUERY_MTU = None
55try:
56 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
57except ImportError:
58 OP_COOKIE_EXCHANGE = None
59try:
60 from OpenSSL.SSL import OP_NO_TICKET
61except ImportError:
62 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040063
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040064try:
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -040065 from OpenSSL.SSL import OP_NO_COMPRESSION
66except ImportError:
67 OP_NO_COMPRESSION = None
68
69try:
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040070 from OpenSSL.SSL import MODE_RELEASE_BUFFERS
71except ImportError:
72 MODE_RELEASE_BUFFERS = None
73
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040074try:
75 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
76except ImportError:
77 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
78
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040079from OpenSSL.SSL import (
80 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
81 SSL_ST_OK, SSL_ST_RENEGOTIATE,
82 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
83 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
84 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
85 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040086
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040087# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
88# to use)
89dhparam = """\
90-----BEGIN DH PARAMETERS-----
91MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
92-----END DH PARAMETERS-----
93"""
94
95
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040096def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040097 return ok
98
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040099
Rick Deanb1ccd562009-07-09 23:52:39 -0500100def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400101 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400102 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400103 """
104 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500105 port = socket()
106 port.bind(('', 0))
107 port.listen(1)
108 client = socket()
109 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400110 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400111 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500112 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500113
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400114 # Let's pass some unencrypted data to make sure our socket connection is
115 # fine. Just one byte, so we don't have to worry about buffers getting
116 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400117 server.send(b("x"))
118 assert client.recv(1024) == b("x")
119 client.send(b("y"))
120 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500121
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400122 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400123 server.setblocking(False)
124 client.setblocking(False)
125
Rick Deanb1ccd562009-07-09 23:52:39 -0500126 return (server, client)
127
128
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400129
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400130def handshake(client, server):
131 conns = [client, server]
132 while conns:
133 for conn in conns:
134 try:
135 conn.do_handshake()
136 except WantReadError:
137 pass
138 else:
139 conns.remove(conn)
140
141
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400142def _create_certificate_chain():
143 """
144 Construct and return a chain of certificates.
145
146 1. A new self-signed certificate authority certificate (cacert)
147 2. A new intermediate certificate signed by cacert (icert)
148 3. A new server certificate signed by icert (scert)
149 """
150 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
151
152 # Step 1
153 cakey = PKey()
154 cakey.generate_key(TYPE_RSA, 512)
155 cacert = X509()
156 cacert.get_subject().commonName = "Authority Certificate"
157 cacert.set_issuer(cacert.get_subject())
158 cacert.set_pubkey(cakey)
159 cacert.set_notBefore(b("20000101000000Z"))
160 cacert.set_notAfter(b("20200101000000Z"))
161 cacert.add_extensions([caext])
162 cacert.set_serial_number(0)
163 cacert.sign(cakey, "sha1")
164
165 # Step 2
166 ikey = PKey()
167 ikey.generate_key(TYPE_RSA, 512)
168 icert = X509()
169 icert.get_subject().commonName = "Intermediate Certificate"
170 icert.set_issuer(cacert.get_subject())
171 icert.set_pubkey(ikey)
172 icert.set_notBefore(b("20000101000000Z"))
173 icert.set_notAfter(b("20200101000000Z"))
174 icert.add_extensions([caext])
175 icert.set_serial_number(0)
176 icert.sign(cakey, "sha1")
177
178 # Step 3
179 skey = PKey()
180 skey.generate_key(TYPE_RSA, 512)
181 scert = X509()
182 scert.get_subject().commonName = "Server Certificate"
183 scert.set_issuer(icert.get_subject())
184 scert.set_pubkey(skey)
185 scert.set_notBefore(b("20000101000000Z"))
186 scert.set_notAfter(b("20200101000000Z"))
187 scert.add_extensions([
188 X509Extension(b('basicConstraints'), True, b('CA:false'))])
189 scert.set_serial_number(0)
190 scert.sign(ikey, "sha1")
191
192 return [(cakey, cacert), (ikey, icert), (skey, scert)]
193
194
195
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400196class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400197 """
198 Helper mixin which defines methods for creating a connected socket pair and
199 for forcing two connected SSL sockets to talk to each other via memory BIOs.
200 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500201 def _loopbackClientFactory(self, socket):
202 client = Connection(Context(TLSv1_METHOD), socket)
203 client.set_connect_state()
204 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400205
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500206
207 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400208 ctx = Context(TLSv1_METHOD)
209 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
210 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500211 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400212 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500213 return server
214
215
216 def _loopback(self, serverFactory=None, clientFactory=None):
217 if serverFactory is None:
218 serverFactory = self._loopbackServerFactory
219 if clientFactory is None:
220 clientFactory = self._loopbackClientFactory
221
222 (server, client) = socket_pair()
223 server = serverFactory(server)
224 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400225
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400226 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400227
228 server.setblocking(True)
229 client.setblocking(True)
230 return server, client
231
232
233 def _interactInMemory(self, client_conn, server_conn):
234 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900235 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400236 objects. Copy bytes back and forth between their send/receive buffers
237 for as long as there is anything to copy. When there is nothing more
Jonathan Ballet648875f2011-07-16 14:14:58 +0900238 to copy, return :py:obj:`None`. If one of them actually manages to deliver
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400239 some application bytes, return a two-tuple of the connection from which
240 the bytes were read and the bytes themselves.
241 """
242 wrote = True
243 while wrote:
244 # Loop until neither side has anything to say
245 wrote = False
246
247 # Copy stuff from each side's send buffer to the other side's
248 # receive buffer.
249 for (read, write) in [(client_conn, server_conn),
250 (server_conn, client_conn)]:
251
252 # Give the side a chance to generate some more bytes, or
253 # succeed.
254 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400255 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400256 except WantReadError:
257 # It didn't succeed, so we'll hope it generated some
258 # output.
259 pass
260 else:
261 # It did succeed, so we'll stop now and let the caller deal
262 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400263 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400264
265 while True:
266 # Keep copying as long as there's more stuff there.
267 try:
268 dirty = read.bio_read(4096)
269 except WantReadError:
270 # Okay, nothing more waiting to be sent. Stop
271 # processing this send buffer.
272 break
273 else:
274 # Keep track of the fact that someone generated some
275 # output.
276 wrote = True
277 write.bio_write(dirty)
278
279
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400280
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400281class VersionTests(TestCase):
282 """
283 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900284 :py:obj:`OpenSSL.SSL.SSLeay_version` and
285 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400286 """
287 def test_OPENSSL_VERSION_NUMBER(self):
288 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900289 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400290 byte and the patch, fix, minor, and major versions in the
291 nibbles above that.
292 """
293 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
294
295
296 def test_SSLeay_version(self):
297 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900298 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400299 one of a number of version strings based on that indicator.
300 """
301 versions = {}
302 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
303 SSLEAY_PLATFORM, SSLEAY_DIR]:
304 version = SSLeay_version(t)
305 versions[version] = t
306 self.assertTrue(isinstance(version, bytes))
307 self.assertEqual(len(versions), 5)
308
309
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400310
311class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400312 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900313 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400314 """
315 def test_method(self):
316 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900317 :py:obj:`Context` can be instantiated with one of :py:obj:`SSLv2_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400318 :py:obj:`SSLv3_METHOD`, :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
319 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400320 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400321 methods = [
322 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
323 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400324 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400325
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400326
327 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
328 for meth in maybe:
329 try:
330 Context(meth)
331 except (Error, ValueError):
332 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
333 # don't. Difficult to say in advance.
334 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400335
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400336 self.assertRaises(TypeError, Context, "")
337 self.assertRaises(ValueError, Context, 10)
338
339
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500340 if not PY3:
341 def test_method_long(self):
342 """
343 On Python 2 :py:class:`Context` accepts values of type
344 :py:obj:`long` as well as :py:obj:`int`.
345 """
346 Context(long(TLSv1_METHOD))
347
348
349
Rick Deane15b1472009-07-09 15:53:42 -0500350 def test_type(self):
351 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900352 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400353 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500354 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400355 self.assertIdentical(Context, ContextType)
356 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500357
358
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400359 def test_use_privatekey(self):
360 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900361 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400362 """
363 key = PKey()
364 key.generate_key(TYPE_RSA, 128)
365 ctx = Context(TLSv1_METHOD)
366 ctx.use_privatekey(key)
367 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400368
369
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800370 def test_use_privatekey_file_missing(self):
371 """
372 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error`
373 when passed the name of a file which does not exist.
374 """
375 ctx = Context(TLSv1_METHOD)
376 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
377
378
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500379 if not PY3:
380 def test_use_privatekey_file_long(self):
381 """
382 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
383 filetype of type :py:obj:`long` as well as :py:obj:`int`.
384 """
385 pemfile = self.mktemp()
386
387 key = PKey()
388 key.generate_key(TYPE_RSA, 128)
389
390 with open(pemfile, "wt") as pem:
391 pem.write(
392 dump_privatekey(FILETYPE_PEM, key).decode("ascii"))
393
394 ctx = Context(TLSv1_METHOD)
395 ctx.use_privatekey_file(pemfile, long(FILETYPE_PEM))
396
397
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800398 def test_use_certificate_wrong_args(self):
399 """
400 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
401 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as an
402 argument.
403 """
404 ctx = Context(TLSv1_METHOD)
405 self.assertRaises(TypeError, ctx.use_certificate)
406 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
407 self.assertRaises(TypeError, ctx.use_certificate, X509(), "hello, world")
408
409
410 def test_use_certificate_uninitialized(self):
411 """
412 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
413 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
414 initialized (ie, which does not actually have any certificate data).
415 """
416 ctx = Context(TLSv1_METHOD)
417 self.assertRaises(Error, ctx.use_certificate, X509())
418
419
420 def test_use_certificate(self):
421 """
422 :py:obj:`Context.use_certificate` sets the certificate which will be
423 used to identify connections created using the context.
424 """
425 # TODO
426 # Hard to assert anything. But we could set a privatekey then ask
427 # OpenSSL if the cert and key agree using check_privatekey. Then as
428 # long as check_privatekey works right we're good...
429 ctx = Context(TLSv1_METHOD)
430 ctx.use_certificate(load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
431
432
433 def test_use_certificate_file_wrong_args(self):
434 """
435 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
436 called with zero arguments or more than two arguments, or if the first
437 argument is not a byte string or the second argumnent is not an integer.
438 """
439 ctx = Context(TLSv1_METHOD)
440 self.assertRaises(TypeError, ctx.use_certificate_file)
441 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile", object())
442 self.assertRaises(
443 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM, object())
444 self.assertRaises(
445 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
446 self.assertRaises(
447 TypeError, ctx.use_certificate_file, b"somefile", object())
448
449
450 def test_use_certificate_file_missing(self):
451 """
452 :py:obj:`Context.use_certificate_file` raises
453 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does not
454 exist.
455 """
456 ctx = Context(TLSv1_METHOD)
457 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
458
459
460 def test_use_certificate_file(self):
461 """
462 :py:obj:`Context.use_certificate` sets the certificate which will be
463 used to identify connections created using the context.
464 """
465 # TODO
466 # Hard to assert anything. But we could set a privatekey then ask
467 # OpenSSL if the cert and key agree using check_privatekey. Then as
468 # long as check_privatekey works right we're good...
469 pem_filename = self.mktemp()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500470 with open(pem_filename, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800471 pem_file.write(cleartextCertificatePEM)
472
473 ctx = Context(TLSv1_METHOD)
474 ctx.use_certificate_file(pem_filename)
475
476
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500477 if not PY3:
478 def test_use_certificate_file_long(self):
479 """
480 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
481 filetype of type :py:obj:`long` as well as :py:obj:`int`.
482 """
483 pem_filename = self.mktemp()
484 with open(pem_filename, "wb") as pem_file:
485 pem_file.write(cleartextCertificatePEM)
486
487 ctx = Context(TLSv1_METHOD)
488 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
489
490
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400491 def test_set_app_data_wrong_args(self):
492 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900493 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called with other than
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400494 one argument.
495 """
496 context = Context(TLSv1_METHOD)
497 self.assertRaises(TypeError, context.set_app_data)
498 self.assertRaises(TypeError, context.set_app_data, None, None)
499
500
501 def test_get_app_data_wrong_args(self):
502 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900503 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400504 arguments.
505 """
506 context = Context(TLSv1_METHOD)
507 self.assertRaises(TypeError, context.get_app_data, None)
508
509
510 def test_app_data(self):
511 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900512 :py:obj:`Context.set_app_data` stores an object for later retrieval using
513 :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400514 """
515 app_data = object()
516 context = Context(TLSv1_METHOD)
517 context.set_app_data(app_data)
518 self.assertIdentical(context.get_app_data(), app_data)
519
520
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400521 def test_set_options_wrong_args(self):
522 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900523 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with the wrong
524 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400525 """
526 context = Context(TLSv1_METHOD)
527 self.assertRaises(TypeError, context.set_options)
528 self.assertRaises(TypeError, context.set_options, None)
529 self.assertRaises(TypeError, context.set_options, 1, None)
530
531
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500532 def test_set_options(self):
533 """
534 :py:obj:`Context.set_options` returns the new options value.
535 """
536 context = Context(TLSv1_METHOD)
537 options = context.set_options(OP_NO_SSLv2)
538 self.assertTrue(OP_NO_SSLv2 & options)
539
540
541 if not PY3:
542 def test_set_options_long(self):
543 """
544 On Python 2 :py:obj:`Context.set_options` accepts values of type
545 :py:obj:`long` as well as :py:obj:`int`.
546 """
547 context = Context(TLSv1_METHOD)
548 options = context.set_options(long(OP_NO_SSLv2))
549 self.assertTrue(OP_NO_SSLv2 & options)
550
551
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300552 def test_set_mode_wrong_args(self):
553 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400554 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with the wrong
555 number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300556 """
557 context = Context(TLSv1_METHOD)
558 self.assertRaises(TypeError, context.set_mode)
559 self.assertRaises(TypeError, context.set_mode, None)
560 self.assertRaises(TypeError, context.set_mode, 1, None)
561
562
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400563 if MODE_RELEASE_BUFFERS is not None:
564 def test_set_mode(self):
565 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400566 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the newly
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400567 set mode.
568 """
569 context = Context(TLSv1_METHOD)
570 self.assertTrue(
571 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500572
573 if not PY3:
574 def test_set_mode_long(self):
575 """
576 On Python 2 :py:obj:`Context.set_mode` accepts values of type
577 :py:obj:`long` as well as :py:obj:`int`.
578 """
579 context = Context(TLSv1_METHOD)
580 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
581 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400582 else:
583 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
584
585
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400586 def test_set_timeout_wrong_args(self):
587 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900588 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with the wrong
589 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400590 """
591 context = Context(TLSv1_METHOD)
592 self.assertRaises(TypeError, context.set_timeout)
593 self.assertRaises(TypeError, context.set_timeout, None)
594 self.assertRaises(TypeError, context.set_timeout, 1, None)
595
596
597 def test_get_timeout_wrong_args(self):
598 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900599 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400600 """
601 context = Context(TLSv1_METHOD)
602 self.assertRaises(TypeError, context.get_timeout, None)
603
604
605 def test_timeout(self):
606 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900607 :py:obj:`Context.set_timeout` sets the session timeout for all connections
608 created using the context object. :py:obj:`Context.get_timeout` retrieves this
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400609 value.
610 """
611 context = Context(TLSv1_METHOD)
612 context.set_timeout(1234)
613 self.assertEquals(context.get_timeout(), 1234)
614
615
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500616 if not PY3:
617 def test_timeout_long(self):
618 """
619 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
620 `long` as well as int.
621 """
622 context = Context(TLSv1_METHOD)
623 context.set_timeout(long(1234))
624 self.assertEquals(context.get_timeout(), 1234)
625
626
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400627 def test_set_verify_depth_wrong_args(self):
628 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900629 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called with the wrong
630 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400631 """
632 context = Context(TLSv1_METHOD)
633 self.assertRaises(TypeError, context.set_verify_depth)
634 self.assertRaises(TypeError, context.set_verify_depth, None)
635 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
636
637
638 def test_get_verify_depth_wrong_args(self):
639 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900640 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400641 """
642 context = Context(TLSv1_METHOD)
643 self.assertRaises(TypeError, context.get_verify_depth, None)
644
645
646 def test_verify_depth(self):
647 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900648 :py:obj:`Context.set_verify_depth` sets the number of certificates in a chain
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400649 to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900650 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400651 """
652 context = Context(TLSv1_METHOD)
653 context.set_verify_depth(11)
654 self.assertEquals(context.get_verify_depth(), 11)
655
656
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500657 if not PY3:
658 def test_verify_depth_long(self):
659 """
660 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
661 type `long` as well as int.
662 """
663 context = Context(TLSv1_METHOD)
664 context.set_verify_depth(long(11))
665 self.assertEquals(context.get_verify_depth(), 11)
666
667
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400668 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400669 """
670 Write a new private key out to a new file, encrypted using the given
671 passphrase. Return the path to the new file.
672 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400673 key = PKey()
674 key.generate_key(TYPE_RSA, 128)
675 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400676 fObj = open(pemFile, 'w')
677 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
678 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400679 fObj.close()
680 return pemFile
681
682
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400683 def test_set_passwd_cb_wrong_args(self):
684 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900685 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called with the
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400686 wrong arguments or with a non-callable first argument.
687 """
688 context = Context(TLSv1_METHOD)
689 self.assertRaises(TypeError, context.set_passwd_cb)
690 self.assertRaises(TypeError, context.set_passwd_cb, None)
691 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
692
693
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400694 def test_set_passwd_cb(self):
695 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900696 :py:obj:`Context.set_passwd_cb` accepts a callable which will be invoked when
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400697 a private key is loaded from an encrypted PEM.
698 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400699 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400700 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400701 calledWith = []
702 def passphraseCallback(maxlen, verify, extra):
703 calledWith.append((maxlen, verify, extra))
704 return passphrase
705 context = Context(TLSv1_METHOD)
706 context.set_passwd_cb(passphraseCallback)
707 context.use_privatekey_file(pemFile)
708 self.assertTrue(len(calledWith), 1)
709 self.assertTrue(isinstance(calledWith[0][0], int))
710 self.assertTrue(isinstance(calledWith[0][1], int))
711 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400712
713
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400714 def test_passwd_callback_exception(self):
715 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900716 :py:obj:`Context.use_privatekey_file` propagates any exception raised by the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400717 passphrase callback.
718 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400719 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400720 def passphraseCallback(maxlen, verify, extra):
721 raise RuntimeError("Sorry, I am a fail.")
722
723 context = Context(TLSv1_METHOD)
724 context.set_passwd_cb(passphraseCallback)
725 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
726
727
728 def test_passwd_callback_false(self):
729 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900730 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400731 passphrase callback returns a false value.
732 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400733 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400734 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500735 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400736
737 context = Context(TLSv1_METHOD)
738 context.set_passwd_cb(passphraseCallback)
739 self.assertRaises(Error, context.use_privatekey_file, pemFile)
740
741
742 def test_passwd_callback_non_string(self):
743 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900744 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400745 passphrase callback returns a true non-string value.
746 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400747 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400748 def passphraseCallback(maxlen, verify, extra):
749 return 10
750
751 context = Context(TLSv1_METHOD)
752 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800753 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400754
755
756 def test_passwd_callback_too_long(self):
757 """
758 If the passphrase returned by the passphrase callback returns a string
759 longer than the indicated maximum length, it is truncated.
760 """
761 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400762 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400763 pemFile = self._write_encrypted_pem(passphrase)
764 def passphraseCallback(maxlen, verify, extra):
765 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400766 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400767
768 context = Context(TLSv1_METHOD)
769 context.set_passwd_cb(passphraseCallback)
770 # This shall succeed because the truncated result is the correct
771 # passphrase.
772 context.use_privatekey_file(pemFile)
773
774
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400775 def test_set_info_callback(self):
776 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900777 :py:obj:`Context.set_info_callback` accepts a callable which will be invoked
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400778 when certain information about an SSL connection is available.
779 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500780 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400781
782 clientSSL = Connection(Context(TLSv1_METHOD), client)
783 clientSSL.set_connect_state()
784
785 called = []
786 def info(conn, where, ret):
787 called.append((conn, where, ret))
788 context = Context(TLSv1_METHOD)
789 context.set_info_callback(info)
790 context.use_certificate(
791 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
792 context.use_privatekey(
793 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
794
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400795 serverSSL = Connection(context, server)
796 serverSSL.set_accept_state()
797
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500798 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400799
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500800 # The callback must always be called with a Connection instance as the
801 # first argument. It would probably be better to split this into
802 # separate tests for client and server side info callbacks so we could
803 # assert it is called with the right Connection instance. It would
804 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500805 notConnections = [
806 conn for (conn, where, ret) in called
807 if not isinstance(conn, Connection)]
808 self.assertEqual(
809 [], notConnections,
810 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400811
812
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400813 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400814 """
815 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400816 its :py:obj:`load_verify_locations` method with the given arguments.
817 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400818 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500819 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400820
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400821 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400822 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400823 # Require that the server certificate verify properly or the
824 # connection will fail.
825 clientContext.set_verify(
826 VERIFY_PEER,
827 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
828
829 clientSSL = Connection(clientContext, client)
830 clientSSL.set_connect_state()
831
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400832 serverContext = Context(TLSv1_METHOD)
833 serverContext.use_certificate(
834 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
835 serverContext.use_privatekey(
836 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
837
838 serverSSL = Connection(serverContext, server)
839 serverSSL.set_accept_state()
840
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400841 # Without load_verify_locations above, the handshake
842 # will fail:
843 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
844 # 'certificate verify failed')]
845 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400846
847 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400848 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400849
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500850
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400851 def test_load_verify_file(self):
852 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900853 :py:obj:`Context.load_verify_locations` accepts a file name and uses the
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400854 certificates within for verification purposes.
855 """
856 cafile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400857 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400858 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400859 fObj.close()
860
861 self._load_verify_locations_test(cafile)
862
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400863
864 def test_load_verify_invalid_file(self):
865 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900866 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when passed a
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400867 non-existent cafile.
868 """
869 clientContext = Context(TLSv1_METHOD)
870 self.assertRaises(
871 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400872
873
874 def test_load_verify_directory(self):
875 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900876 :py:obj:`Context.load_verify_locations` accepts a directory name and uses
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400877 the certificates within for verification purposes.
878 """
879 capath = self.mktemp()
880 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400881 # Hash values computed manually with c_rehash to avoid depending on
882 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
883 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500884 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400885 cafile = join(capath, name)
886 fObj = open(cafile, 'w')
887 fObj.write(cleartextCertificatePEM.decode('ascii'))
888 fObj.close()
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400889
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400890 self._load_verify_locations_test(None, capath)
891
892
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400893 def test_load_verify_locations_wrong_args(self):
894 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900895 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if called with
896 the wrong number of arguments or with non-:py:obj:`str` arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400897 """
898 context = Context(TLSv1_METHOD)
899 self.assertRaises(TypeError, context.load_verify_locations)
900 self.assertRaises(TypeError, context.load_verify_locations, object())
901 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
902 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
903
904
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400905 if platform == "win32":
906 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400907 "See LP#404343 and LP#404344."
908 else:
909 def test_set_default_verify_paths(self):
910 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900911 :py:obj:`Context.set_default_verify_paths` causes the platform-specific CA
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400912 certificate locations to be used for verification purposes.
913 """
914 # Testing this requires a server with a certificate signed by one of
915 # the CAs in the platform CA location. Getting one of those costs
916 # money. Fortunately (or unfortunately, depending on your
917 # perspective), it's easy to think of a public server on the
918 # internet which has such a certificate. Connecting to the network
919 # in a unit test is bad, but it's the only way I can think of to
920 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400921
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400922 # Arg, verisign.com doesn't speak TLSv1
923 context = Context(SSLv3_METHOD)
924 context.set_default_verify_paths()
925 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +0200926 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400927 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400928
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400929 client = socket()
930 client.connect(('verisign.com', 443))
931 clientSSL = Connection(context, client)
932 clientSSL.set_connect_state()
933 clientSSL.do_handshake()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500934 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400935 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400936
937
938 def test_set_default_verify_paths_signature(self):
939 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900940 :py:obj:`Context.set_default_verify_paths` takes no arguments and raises
941 :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400942 """
943 context = Context(TLSv1_METHOD)
944 self.assertRaises(TypeError, context.set_default_verify_paths, None)
945 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
946 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500947
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400948
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500949 def test_add_extra_chain_cert_invalid_cert(self):
950 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900951 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if called with
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500952 other than one argument or if called with an object which is not an
Jonathan Ballet648875f2011-07-16 14:14:58 +0900953 instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500954 """
955 context = Context(TLSv1_METHOD)
956 self.assertRaises(TypeError, context.add_extra_chain_cert)
957 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
958 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
959
960
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400961 def _handshake_test(self, serverContext, clientContext):
962 """
963 Verify that a client and server created with the given contexts can
964 successfully handshake and communicate.
965 """
966 serverSocket, clientSocket = socket_pair()
967
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400968 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400969 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400970
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400971 client = Connection(clientContext, clientSocket)
972 client.set_connect_state()
973
974 # Make them talk to each other.
975 # self._interactInMemory(client, server)
976 for i in range(3):
977 for s in [client, server]:
978 try:
979 s.do_handshake()
980 except WantReadError:
981 pass
982
983
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800984 def test_set_verify_callback_exception(self):
985 """
986 If the verify callback passed to :py:obj:`Context.set_verify` raises an
987 exception, verification fails and the exception is propagated to the
988 caller of :py:obj:`Connection.do_handshake`.
989 """
990 serverContext = Context(TLSv1_METHOD)
991 serverContext.use_privatekey(
992 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
993 serverContext.use_certificate(
994 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
995
996 clientContext = Context(TLSv1_METHOD)
997 def verify_callback(*args):
998 raise Exception("silly verify failure")
999 clientContext.set_verify(VERIFY_PEER, verify_callback)
1000
1001 exc = self.assertRaises(
1002 Exception, self._handshake_test, serverContext, clientContext)
1003 self.assertEqual("silly verify failure", str(exc))
1004
1005
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001006 def test_add_extra_chain_cert(self):
1007 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001008 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509` instance to add to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001009 the certificate chain.
1010
Jonathan Ballet648875f2011-07-16 14:14:58 +09001011 See :py:obj:`_create_certificate_chain` for the details of the certificate
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001012 chain tested.
1013
1014 The chain is tested by starting a server with scert and connecting
1015 to it with a client which trusts cacert and requires verification to
1016 succeed.
1017 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001018 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001019 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1020
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001021 # Dump the CA certificate to a file because that's the only way to load
1022 # it as a trusted CA in the client context.
1023 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001024 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001025 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001026 fObj.close()
1027
1028 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001029 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001030 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001031 fObj.close()
1032
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001033 # Create the server context
1034 serverContext = Context(TLSv1_METHOD)
1035 serverContext.use_privatekey(skey)
1036 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001037 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001038 serverContext.add_extra_chain_cert(icert)
1039
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001040 # Create the client
1041 clientContext = Context(TLSv1_METHOD)
1042 clientContext.set_verify(
1043 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001044 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001045
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001046 # Try it out.
1047 self._handshake_test(serverContext, clientContext)
1048
1049
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001050 def test_use_certificate_chain_file(self):
1051 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001052 :py:obj:`Context.use_certificate_chain_file` reads a certificate chain from
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001053 the specified file.
1054
1055 The chain is tested by starting a server with scert and connecting
1056 to it with a client which trusts cacert and requires verification to
1057 succeed.
1058 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001059 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001060 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1061
1062 # Write out the chain file.
1063 chainFile = self.mktemp()
Jean-Paul Calderoned8607982014-01-18 10:30:55 -05001064 fObj = open(chainFile, 'wb')
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001065 # Most specific to least general.
Jean-Paul Calderoned8607982014-01-18 10:30:55 -05001066 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1067 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1068 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001069 fObj.close()
1070
1071 serverContext = Context(TLSv1_METHOD)
1072 serverContext.use_certificate_chain_file(chainFile)
1073 serverContext.use_privatekey(skey)
1074
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001075 fObj = open('ca.pem', 'w')
1076 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001077 fObj.close()
1078
1079 clientContext = Context(TLSv1_METHOD)
1080 clientContext.set_verify(
1081 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001082 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001083
1084 self._handshake_test(serverContext, clientContext)
1085
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001086
1087 def test_use_certificate_chain_file_wrong_args(self):
1088 """
1089 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1090 if passed zero or more than one argument or when passed a non-byte
1091 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error` when
1092 passed a bad chain file name (for example, the name of a file which does
1093 not exist).
1094 """
1095 context = Context(TLSv1_METHOD)
1096 self.assertRaises(TypeError, context.use_certificate_chain_file)
1097 self.assertRaises(TypeError, context.use_certificate_chain_file, object())
1098 self.assertRaises(TypeError, context.use_certificate_chain_file, b"foo", object())
1099
1100 self.assertRaises(Error, context.use_certificate_chain_file, self.mktemp())
1101
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001102 # XXX load_client_ca
1103 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001104
1105 def test_get_verify_mode_wrong_args(self):
1106 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001107 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001108 arguments.
1109 """
1110 context = Context(TLSv1_METHOD)
1111 self.assertRaises(TypeError, context.get_verify_mode, None)
1112
1113
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001114 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001115 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001116 :py:obj:`Context.get_verify_mode` returns the verify mode flags previously
1117 passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001118 """
1119 context = Context(TLSv1_METHOD)
1120 self.assertEquals(context.get_verify_mode(), 0)
1121 context.set_verify(
1122 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1123 self.assertEquals(
1124 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1125
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001126
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001127 if not PY3:
1128 def test_set_verify_mode_long(self):
1129 """
1130 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1131 type :py:obj:`long` as well as :py:obj:`int`.
1132 """
1133 context = Context(TLSv1_METHOD)
1134 self.assertEquals(context.get_verify_mode(), 0)
1135 context.set_verify(
1136 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None)
1137 self.assertEquals(
1138 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1139
1140
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001141 def test_load_tmp_dh_wrong_args(self):
1142 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001143 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
1144 number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001145 """
1146 context = Context(TLSv1_METHOD)
1147 self.assertRaises(TypeError, context.load_tmp_dh)
1148 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1149 self.assertRaises(TypeError, context.load_tmp_dh, object())
1150
1151
1152 def test_load_tmp_dh_missing_file(self):
1153 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001154 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the specified file
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001155 does not exist.
1156 """
1157 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001158 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001159
1160
1161 def test_load_tmp_dh(self):
1162 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001163 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001164 specified file.
1165 """
1166 context = Context(TLSv1_METHOD)
1167 dhfilename = self.mktemp()
1168 dhfile = open(dhfilename, "w")
1169 dhfile.write(dhparam)
1170 dhfile.close()
1171 context.load_tmp_dh(dhfilename)
1172 # XXX What should I assert here? -exarkun
1173
1174
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001175 def test_set_cipher_list_bytes(self):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001176 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001177 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
1178 ciphers which connections created with the context object will be able
1179 to choose from.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001180 """
1181 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001182 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001183 conn = Connection(context, None)
1184 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001185
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001186
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001187 def test_set_cipher_list_text(self):
1188 """
1189 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
1190 the ciphers which connections created with the context object will be
1191 able to choose from.
1192 """
1193 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -05001194 context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001195 conn = Connection(context, None)
1196 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
1197
1198
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001199 def test_set_cipher_list_wrong_args(self):
1200 """
Jean-Paul Calderone17044832014-01-18 10:20:11 -05001201 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
1202 passed zero arguments or more than one argument or when passed a
1203 non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001204 passed an incorrect cipher list string.
1205 """
1206 context = Context(TLSv1_METHOD)
1207 self.assertRaises(TypeError, context.set_cipher_list)
1208 self.assertRaises(TypeError, context.set_cipher_list, object())
1209 self.assertRaises(TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object())
1210
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001211 self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001212
1213
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001214 def test_set_session_cache_mode_wrong_args(self):
1215 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001216 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1217 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001218 """
1219 context = Context(TLSv1_METHOD)
1220 self.assertRaises(TypeError, context.set_session_cache_mode)
1221 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1222
1223
1224 def test_get_session_cache_mode_wrong_args(self):
1225 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001226 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1227 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001228 """
1229 context = Context(TLSv1_METHOD)
1230 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1231
1232
1233 def test_session_cache_mode(self):
1234 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001235 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1236 cached. The setting can be retrieved via
1237 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001238 """
1239 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001240 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001241 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1242 self.assertEqual(SESS_CACHE_OFF, off)
1243 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1244
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001245 if not PY3:
1246 def test_session_cache_mode_long(self):
1247 """
1248 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1249 of type :py:obj:`long` as well as :py:obj:`int`.
1250 """
1251 context = Context(TLSv1_METHOD)
1252 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1253 self.assertEqual(
1254 SESS_CACHE_BOTH, context.get_session_cache_mode())
1255
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001256
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001257 def test_get_cert_store(self):
1258 """
1259 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store` instance.
1260 """
1261 context = Context(TLSv1_METHOD)
1262 store = context.get_cert_store()
1263 self.assertIsInstance(store, X509Store)
1264
1265
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001266
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001267class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1268 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001269 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
1270 :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001271 """
1272 def test_wrong_args(self):
1273 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001274 :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001275 with other than one argument.
1276 """
1277 context = Context(TLSv1_METHOD)
1278 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1279 self.assertRaises(
1280 TypeError, context.set_tlsext_servername_callback, 1, 2)
1281
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001282
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001283 def test_old_callback_forgotten(self):
1284 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001285 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001286 callback, the one it replaces is dereferenced.
1287 """
1288 def callback(connection):
1289 pass
1290
1291 def replacement(connection):
1292 pass
1293
1294 context = Context(TLSv1_METHOD)
1295 context.set_tlsext_servername_callback(callback)
1296
1297 tracker = ref(callback)
1298 del callback
1299
1300 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001301
1302 # One run of the garbage collector happens to work on CPython. PyPy
1303 # doesn't collect the underlying object until a second run for whatever
1304 # reason. That's fine, it still demonstrates our code has properly
1305 # dropped the reference.
1306 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001307 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001308
1309 callback = tracker()
1310 if callback is not None:
1311 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001312 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001313 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001314
1315
1316 def test_no_servername(self):
1317 """
1318 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001319 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
1320 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001321 """
1322 args = []
1323 def servername(conn):
1324 args.append((conn, conn.get_servername()))
1325 context = Context(TLSv1_METHOD)
1326 context.set_tlsext_servername_callback(servername)
1327
1328 # Lose our reference to it. The Context is responsible for keeping it
1329 # alive now.
1330 del servername
1331 collect()
1332
1333 # Necessary to actually accept the connection
1334 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1335 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1336
1337 # Do a little connection to trigger the logic
1338 server = Connection(context, None)
1339 server.set_accept_state()
1340
1341 client = Connection(Context(TLSv1_METHOD), None)
1342 client.set_connect_state()
1343
1344 self._interactInMemory(server, client)
1345
1346 self.assertEqual([(server, None)], args)
1347
1348
1349 def test_servername(self):
1350 """
1351 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +09001352 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
1353 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001354 """
1355 args = []
1356 def servername(conn):
1357 args.append((conn, conn.get_servername()))
1358 context = Context(TLSv1_METHOD)
1359 context.set_tlsext_servername_callback(servername)
1360
1361 # Necessary to actually accept the connection
1362 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1363 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1364
1365 # Do a little connection to trigger the logic
1366 server = Connection(context, None)
1367 server.set_accept_state()
1368
1369 client = Connection(Context(TLSv1_METHOD), None)
1370 client.set_connect_state()
1371 client.set_tlsext_host_name(b("foo1.example.com"))
1372
1373 self._interactInMemory(server, client)
1374
1375 self.assertEqual([(server, b("foo1.example.com"))], args)
1376
1377
1378
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001379class SessionTests(TestCase):
1380 """
1381 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1382 """
1383 def test_construction(self):
1384 """
1385 :py:class:`Session` can be constructed with no arguments, creating a new
1386 instance of that type.
1387 """
1388 new_session = Session()
1389 self.assertTrue(isinstance(new_session, Session))
1390
1391
1392 def test_construction_wrong_args(self):
1393 """
1394 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
1395 is raised.
1396 """
1397 self.assertRaises(TypeError, Session, 123)
1398 self.assertRaises(TypeError, Session, "hello")
1399 self.assertRaises(TypeError, Session, object())
1400
1401
1402
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001403class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05001404 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001405 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001406 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001407 # XXX get_peer_certificate -> None
1408 # XXX sock_shutdown
1409 # XXX master_key -> TypeError
1410 # XXX server_random -> TypeError
1411 # XXX state_string
1412 # XXX connect -> TypeError
1413 # XXX connect_ex -> TypeError
1414 # XXX set_connect_state -> TypeError
1415 # XXX set_accept_state -> TypeError
1416 # XXX renegotiate_pending
1417 # XXX do_handshake -> TypeError
1418 # XXX bio_read -> TypeError
1419 # XXX recv -> TypeError
1420 # XXX send -> TypeError
1421 # XXX bio_write -> TypeError
1422
Rick Deane15b1472009-07-09 15:53:42 -05001423 def test_type(self):
1424 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001425 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001426 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05001427 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001428 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05001429 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001430 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05001431
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001432
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001433 def test_get_context(self):
1434 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001435 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
1436 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001437 """
1438 context = Context(TLSv1_METHOD)
1439 connection = Connection(context, None)
1440 self.assertIdentical(connection.get_context(), context)
1441
1442
1443 def test_get_context_wrong_args(self):
1444 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001445 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001446 arguments.
1447 """
1448 connection = Connection(Context(TLSv1_METHOD), None)
1449 self.assertRaises(TypeError, connection.get_context, None)
1450
1451
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001452 def test_set_context_wrong_args(self):
1453 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001454 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
1455 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001456 than 1.
1457 """
1458 ctx = Context(TLSv1_METHOD)
1459 connection = Connection(ctx, None)
1460 self.assertRaises(TypeError, connection.set_context)
1461 self.assertRaises(TypeError, connection.set_context, object())
1462 self.assertRaises(TypeError, connection.set_context, "hello")
1463 self.assertRaises(TypeError, connection.set_context, 1)
1464 self.assertRaises(TypeError, connection.set_context, 1, 2)
1465 self.assertRaises(
1466 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
1467 self.assertIdentical(ctx, connection.get_context())
1468
1469
1470 def test_set_context(self):
1471 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001472 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001473 for the connection.
1474 """
1475 original = Context(SSLv23_METHOD)
1476 replacement = Context(TLSv1_METHOD)
1477 connection = Connection(original, None)
1478 connection.set_context(replacement)
1479 self.assertIdentical(replacement, connection.get_context())
1480 # Lose our references to the contexts, just in case the Connection isn't
1481 # properly managing its own contributions to their reference counts.
1482 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001483 collect()
1484
1485
1486 def test_set_tlsext_host_name_wrong_args(self):
1487 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001488 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001489 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09001490 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001491 """
1492 conn = Connection(Context(TLSv1_METHOD), None)
1493 self.assertRaises(TypeError, conn.set_tlsext_host_name)
1494 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
1495 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
1496 self.assertRaises(
1497 TypeError, conn.set_tlsext_host_name, b("with\0null"))
1498
1499 if version_info >= (3,):
1500 # On Python 3.x, don't accidentally implicitly convert from text.
1501 self.assertRaises(
1502 TypeError,
1503 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001504
1505
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001506 def test_get_servername_wrong_args(self):
1507 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001508 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001509 arguments.
1510 """
1511 connection = Connection(Context(TLSv1_METHOD), None)
1512 self.assertRaises(TypeError, connection.get_servername, object())
1513 self.assertRaises(TypeError, connection.get_servername, 1)
1514 self.assertRaises(TypeError, connection.get_servername, "hello")
1515
1516
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001517 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001518 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001519 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001520 immediate read.
1521 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001522 connection = Connection(Context(TLSv1_METHOD), None)
1523 self.assertEquals(connection.pending(), 0)
1524
1525
1526 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001527 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001528 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001529 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001530 connection = Connection(Context(TLSv1_METHOD), None)
1531 self.assertRaises(TypeError, connection.pending, None)
1532
1533
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001534 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001535 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001536 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001537 argument or with the wrong number of arguments.
1538 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001539 connection = Connection(Context(TLSv1_METHOD), socket())
1540 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001541 self.assertRaises(TypeError, connection.connect)
1542 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001543
1544
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001545 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001546 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001547 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001548 connect method raises it.
1549 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001550 client = socket()
1551 context = Context(TLSv1_METHOD)
1552 clientSSL = Connection(context, client)
1553 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04001554 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001555
1556
1557 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001558 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001559 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001560 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001561 port = socket()
1562 port.bind(('', 0))
1563 port.listen(3)
1564
1565 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001566 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
1567 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001568
1569
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001570 if platform == "darwin":
1571 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
1572 else:
1573 def test_connect_ex(self):
1574 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001575 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001576 errno instead of raising an exception.
1577 """
1578 port = socket()
1579 port.bind(('', 0))
1580 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001581
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001582 clientSSL = Connection(Context(TLSv1_METHOD), socket())
1583 clientSSL.setblocking(False)
1584 result = clientSSL.connect_ex(port.getsockname())
1585 expected = (EINPROGRESS, EWOULDBLOCK)
1586 self.assertTrue(
1587 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001588
1589
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001590 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001591 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001592 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001593 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001594 connection = Connection(Context(TLSv1_METHOD), socket())
1595 self.assertRaises(TypeError, connection.accept, None)
1596
1597
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001598 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001599 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001600 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
1601 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001602 connection originated from.
1603 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001604 ctx = Context(TLSv1_METHOD)
1605 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1606 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001607 port = socket()
1608 portSSL = Connection(ctx, port)
1609 portSSL.bind(('', 0))
1610 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001611
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001612 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001613
1614 # Calling portSSL.getsockname() here to get the server IP address sounds
1615 # great, but frequently fails on Windows.
1616 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001617
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001618 serverSSL, address = portSSL.accept()
1619
1620 self.assertTrue(isinstance(serverSSL, Connection))
1621 self.assertIdentical(serverSSL.get_context(), ctx)
1622 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001623
1624
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001625 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001626 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001627 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001628 number of arguments or with arguments other than integers.
1629 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001630 connection = Connection(Context(TLSv1_METHOD), None)
1631 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04001632 self.assertRaises(TypeError, connection.get_shutdown, None)
1633 self.assertRaises(TypeError, connection.set_shutdown)
1634 self.assertRaises(TypeError, connection.set_shutdown, None)
1635 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001636
1637
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001638 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001639 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001640 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001641 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001642 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001643 self.assertFalse(server.shutdown())
1644 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001645 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001646 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
1647 client.shutdown()
1648 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
1649 self.assertRaises(ZeroReturnError, server.recv, 1024)
1650 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001651
1652
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001653 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001654 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001655 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001656 process.
1657 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001658 connection = Connection(Context(TLSv1_METHOD), socket())
1659 connection.set_shutdown(RECEIVED_SHUTDOWN)
1660 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1661
1662
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05001663 if not PY3:
1664 def test_set_shutdown_long(self):
1665 """
1666 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
1667 of type :py:obj:`long` as well as :py:obj:`int`.
1668 """
1669 connection = Connection(Context(TLSv1_METHOD), socket())
1670 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
1671 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1672
1673
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001674 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001675 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001676 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
1677 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001678 with any arguments.
1679 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001680 conn = Connection(Context(TLSv1_METHOD), None)
1681 self.assertRaises(TypeError, conn.get_app_data, None)
1682 self.assertRaises(TypeError, conn.set_app_data)
1683 self.assertRaises(TypeError, conn.set_app_data, None, None)
1684
1685
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001686 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001687 """
1688 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001689 :py:obj:`Connection.set_app_data` and later retrieved with
1690 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001691 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001692 conn = Connection(Context(TLSv1_METHOD), None)
1693 app_data = object()
1694 conn.set_app_data(app_data)
1695 self.assertIdentical(conn.get_app_data(), app_data)
1696
1697
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001698 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001699 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001700 :py:obj:`Connection.makefile` is not implemented and calling that method raises
1701 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001702 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001703 conn = Connection(Context(TLSv1_METHOD), None)
1704 self.assertRaises(NotImplementedError, conn.makefile)
1705
1706
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001707 def test_get_peer_cert_chain_wrong_args(self):
1708 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001709 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001710 arguments.
1711 """
1712 conn = Connection(Context(TLSv1_METHOD), None)
1713 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
1714 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
1715 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
1716 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
1717
1718
1719 def test_get_peer_cert_chain(self):
1720 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001721 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001722 the connected server returned for the certification verification.
1723 """
1724 chain = _create_certificate_chain()
1725 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1726
1727 serverContext = Context(TLSv1_METHOD)
1728 serverContext.use_privatekey(skey)
1729 serverContext.use_certificate(scert)
1730 serverContext.add_extra_chain_cert(icert)
1731 serverContext.add_extra_chain_cert(cacert)
1732 server = Connection(serverContext, None)
1733 server.set_accept_state()
1734
1735 # Create the client
1736 clientContext = Context(TLSv1_METHOD)
1737 clientContext.set_verify(VERIFY_NONE, verify_cb)
1738 client = Connection(clientContext, None)
1739 client.set_connect_state()
1740
1741 self._interactInMemory(client, server)
1742
1743 chain = client.get_peer_cert_chain()
1744 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001745 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001746 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001747 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001748 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001749 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001750 "Authority Certificate", chain[2].get_subject().CN)
1751
1752
1753 def test_get_peer_cert_chain_none(self):
1754 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001755 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001756 certificate chain.
1757 """
1758 ctx = Context(TLSv1_METHOD)
1759 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1760 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1761 server = Connection(ctx, None)
1762 server.set_accept_state()
1763 client = Connection(Context(TLSv1_METHOD), None)
1764 client.set_connect_state()
1765 self._interactInMemory(client, server)
1766 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001767
1768
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001769 def test_get_session_wrong_args(self):
1770 """
1771 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
1772 with any arguments.
1773 """
1774 ctx = Context(TLSv1_METHOD)
1775 server = Connection(ctx, None)
1776 self.assertRaises(TypeError, server.get_session, 123)
1777 self.assertRaises(TypeError, server.get_session, "hello")
1778 self.assertRaises(TypeError, server.get_session, object())
1779
1780
1781 def test_get_session_unconnected(self):
1782 """
1783 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
1784 an object which has not been connected.
1785 """
1786 ctx = Context(TLSv1_METHOD)
1787 server = Connection(ctx, None)
1788 session = server.get_session()
1789 self.assertIdentical(None, session)
1790
1791
1792 def test_server_get_session(self):
1793 """
1794 On the server side of a connection, :py:obj:`Connection.get_session`
1795 returns a :py:class:`Session` instance representing the SSL session for
1796 that connection.
1797 """
1798 server, client = self._loopback()
1799 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001800 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001801
1802
1803 def test_client_get_session(self):
1804 """
1805 On the client side of a connection, :py:obj:`Connection.get_session`
1806 returns a :py:class:`Session` instance representing the SSL session for
1807 that connection.
1808 """
1809 server, client = self._loopback()
1810 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001811 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001812
1813
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05001814 def test_set_session_wrong_args(self):
1815 """
1816 If called with an object that is not an instance of :py:class:`Session`,
1817 or with other than one argument, :py:obj:`Connection.set_session` raises
1818 :py:obj:`TypeError`.
1819 """
1820 ctx = Context(TLSv1_METHOD)
1821 connection = Connection(ctx, None)
1822 self.assertRaises(TypeError, connection.set_session)
1823 self.assertRaises(TypeError, connection.set_session, 123)
1824 self.assertRaises(TypeError, connection.set_session, "hello")
1825 self.assertRaises(TypeError, connection.set_session, object())
1826 self.assertRaises(
1827 TypeError, connection.set_session, Session(), Session())
1828
1829
1830 def test_client_set_session(self):
1831 """
1832 :py:obj:`Connection.set_session`, when used prior to a connection being
1833 established, accepts a :py:class:`Session` instance and causes an
1834 attempt to re-use the session it represents when the SSL handshake is
1835 performed.
1836 """
1837 key = load_privatekey(FILETYPE_PEM, server_key_pem)
1838 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
1839 ctx = Context(TLSv1_METHOD)
1840 ctx.use_privatekey(key)
1841 ctx.use_certificate(cert)
1842 ctx.set_session_id("unity-test")
1843
1844 def makeServer(socket):
1845 server = Connection(ctx, socket)
1846 server.set_accept_state()
1847 return server
1848
1849 originalServer, originalClient = self._loopback(
1850 serverFactory=makeServer)
1851 originalSession = originalClient.get_session()
1852
1853 def makeClient(socket):
1854 client = self._loopbackClientFactory(socket)
1855 client.set_session(originalSession)
1856 return client
1857 resumedServer, resumedClient = self._loopback(
1858 serverFactory=makeServer,
1859 clientFactory=makeClient)
1860
1861 # This is a proxy: in general, we have no access to any unique
1862 # identifier for the session (new enough versions of OpenSSL expose a
1863 # hash which could be usable, but "new enough" is very, very new).
1864 # Instead, exploit the fact that the master key is re-used if the
1865 # session is re-used. As long as the master key for the two connections
1866 # is the same, the session was re-used!
1867 self.assertEqual(
1868 originalServer.master_key(), resumedServer.master_key())
1869
1870
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05001871 def test_set_session_wrong_method(self):
1872 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05001873 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
1874 instance associated with a context using a different SSL method than the
1875 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
1876 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05001877 """
1878 key = load_privatekey(FILETYPE_PEM, server_key_pem)
1879 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
1880 ctx = Context(TLSv1_METHOD)
1881 ctx.use_privatekey(key)
1882 ctx.use_certificate(cert)
1883 ctx.set_session_id("unity-test")
1884
1885 def makeServer(socket):
1886 server = Connection(ctx, socket)
1887 server.set_accept_state()
1888 return server
1889
1890 originalServer, originalClient = self._loopback(
1891 serverFactory=makeServer)
1892 originalSession = originalClient.get_session()
1893
1894 def makeClient(socket):
1895 # Intentionally use a different, incompatible method here.
1896 client = Connection(Context(SSLv3_METHOD), socket)
1897 client.set_connect_state()
1898 client.set_session(originalSession)
1899 return client
1900
1901 self.assertRaises(
1902 Error,
1903 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
1904
1905
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07001906 def test_wantWriteError(self):
1907 """
1908 :py:obj:`Connection` methods which generate output raise
1909 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
1910 fail indicating a should-write state.
1911 """
1912 client_socket, server_socket = socket_pair()
1913 # Fill up the client's send buffer so Connection won't be able to write
1914 # anything.
Jean-Paul Calderone7d7c9c22014-02-18 16:38:26 -05001915 msg = b"x" * 512
Jean-Paul Calderone22c28b42014-02-18 16:40:34 -05001916 for i in range(2048):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07001917 try:
1918 client_socket.send(msg)
1919 except error as e:
1920 if e.errno == EWOULDBLOCK:
1921 break
1922 raise
1923 else:
1924 self.fail(
1925 "Failed to fill socket buffer, cannot test BIO want write")
1926
1927 ctx = Context(TLSv1_METHOD)
1928 conn = Connection(ctx, client_socket)
1929 # Client's speak first, so make it an SSL client
1930 conn.set_connect_state()
1931 self.assertRaises(WantWriteError, conn.do_handshake)
1932
1933 # XXX want_read
1934
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01001935 def test_get_cipher_name_before_connect(self):
1936 """
1937 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None`
1938 if no connection has been established.
1939 """
1940 ctx = Context(TLSv1_METHOD)
1941 conn = Connection(ctx, None)
1942 self.assertIs(conn.get_cipher_name(), None)
1943
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001944 def test_get_cipher_name(self):
1945 """
1946 :py:obj:`Connection.get_cipher_name` returns the name of the currently
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01001947 used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001948 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001949 server, client = self._loopback()
1950 server_cipher_name, client_cipher_name = \
1951 server.get_cipher_name(), client.get_cipher_name()
1952
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01001953 self.assertIsInstance(server_cipher_name, str)
1954 self.assertIsInstance(client_cipher_name, str)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001955
1956 self.assertEqual(server_cipher_name, client_cipher_name)
1957
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01001958 def test_get_cipher_version_before_connect(self):
1959 """
1960 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None`
1961 if no connection has been established.
1962 """
1963 ctx = Context(TLSv1_METHOD)
1964 conn = Connection(ctx, None)
1965 self.assertIs(conn.get_cipher_version(), None)
1966
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001967 def test_get_cipher_version(self):
1968 """
1969 :py:obj:`Connection.get_cipher_version` returns the protocol name of the currently
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01001970 used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001971 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001972 server, client = self._loopback()
1973 server_cipher_version, client_cipher_version = \
1974 server.get_cipher_version(), client.get_cipher_version()
1975
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01001976 self.assertIsInstance(server_cipher_version, str)
1977 self.assertIsInstance(client_cipher_version, str)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001978
1979 self.assertEqual(server_cipher_version, client_cipher_version)
1980
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01001981 def test_get_cipher_bits_before_connect(self):
1982 """
1983 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None`
1984 if no connection has been established.
1985 """
1986 ctx = Context(TLSv1_METHOD)
1987 conn = Connection(ctx, None)
1988 self.assertIs(conn.get_cipher_bits(), None)
1989
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001990 def test_get_cipher_bits(self):
1991 """
1992 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits of the currently
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01001993 used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001994 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001995 server, client = self._loopback()
1996 server_cipher_bits, client_cipher_bits = \
1997 server.get_cipher_bits(), client.get_cipher_bits()
1998
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01001999 self.assertIsInstance(server_cipher_bits, int)
2000 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002001
2002 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002003
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002004class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002005 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002006 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002007 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002008 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002009 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002010 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002011 arguments.
2012 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002013 connection = Connection(Context(TLSv1_METHOD), None)
2014 self.assertRaises(TypeError, connection.get_cipher_list, None)
2015
2016
2017 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002018 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002019 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2020 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002021 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002022 connection = Connection(Context(TLSv1_METHOD), None)
2023 ciphers = connection.get_cipher_list()
2024 self.assertTrue(isinstance(ciphers, list))
2025 for cipher in ciphers:
2026 self.assertTrue(isinstance(cipher, str))
2027
2028
2029
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002030class ConnectionSendTests(TestCase, _LoopbackMixin):
2031 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002032 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002033 """
2034 def test_wrong_args(self):
2035 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002036 When called with arguments other than string argument for its first
2037 parameter or more than two arguments, :py:obj:`Connection.send` raises
2038 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002039 """
2040 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002041 self.assertRaises(TypeError, connection.send)
2042 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002043 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002044
2045
2046 def test_short_bytes(self):
2047 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002048 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002049 and returns the number of bytes sent.
2050 """
2051 server, client = self._loopback()
2052 count = server.send(b('xy'))
2053 self.assertEquals(count, 2)
2054 self.assertEquals(client.recv(2), b('xy'))
2055
2056 try:
2057 memoryview
2058 except NameError:
2059 "cannot test sending memoryview without memoryview"
2060 else:
2061 def test_short_memoryview(self):
2062 """
2063 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002064 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002065 bytes sent.
2066 """
2067 server, client = self._loopback()
2068 count = server.send(memoryview(b('xy')))
2069 self.assertEquals(count, 2)
2070 self.assertEquals(client.recv(2), b('xy'))
2071
2072
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002073
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002074class ConnectionSendallTests(TestCase, _LoopbackMixin):
2075 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002076 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002077 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002078 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002079 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002080 When called with arguments other than a string argument for its first
2081 parameter or with more than two arguments, :py:obj:`Connection.sendall`
2082 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002083 """
2084 connection = Connection(Context(TLSv1_METHOD), None)
2085 self.assertRaises(TypeError, connection.sendall)
2086 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002087 self.assertRaises(
2088 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002089
2090
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002091 def test_short(self):
2092 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002093 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002094 it.
2095 """
2096 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04002097 server.sendall(b('x'))
2098 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002099
2100
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002101 try:
2102 memoryview
2103 except NameError:
2104 "cannot test sending memoryview without memoryview"
2105 else:
2106 def test_short_memoryview(self):
2107 """
2108 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002109 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002110 """
2111 server, client = self._loopback()
2112 server.sendall(memoryview(b('x')))
2113 self.assertEquals(client.recv(1), b('x'))
2114
2115
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002116 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002117 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002118 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002119 it even if this requires multiple calls of an underlying write function.
2120 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002121 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04002122 # Should be enough, underlying SSL_write should only do 16k at a time.
2123 # On Windows, after 32k of bytes the write will block (forever - because
2124 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04002125 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002126 server.sendall(message)
2127 accum = []
2128 received = 0
2129 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04002130 data = client.recv(1024)
2131 accum.append(data)
2132 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04002133 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002134
2135
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002136 def test_closed(self):
2137 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002138 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002139 write error from the low level write call.
2140 """
2141 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04002142 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002143 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02002144 if platform == "win32":
2145 self.assertEqual(exc.args[0], ESHUTDOWN)
2146 else:
2147 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002148
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002149
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002150
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002151class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
2152 """
2153 Tests for SSL renegotiation APIs.
2154 """
2155 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002156 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002157 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002158 arguments.
2159 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002160 connection = Connection(Context(TLSv1_METHOD), None)
2161 self.assertRaises(TypeError, connection.renegotiate, None)
2162
2163
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002164 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002165 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002166 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002167 any arguments.
2168 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002169 connection = Connection(Context(TLSv1_METHOD), None)
2170 self.assertRaises(TypeError, connection.total_renegotiations, None)
2171
2172
2173 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002174 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002175 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002176 renegotiations have happened.
2177 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002178 connection = Connection(Context(TLSv1_METHOD), None)
2179 self.assertEquals(connection.total_renegotiations(), 0)
2180
2181
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002182# def test_renegotiate(self):
2183# """
2184# """
2185# server, client = self._loopback()
2186
2187# server.send("hello world")
2188# self.assertEquals(client.recv(len("hello world")), "hello world")
2189
2190# self.assertEquals(server.total_renegotiations(), 0)
2191# self.assertTrue(server.renegotiate())
2192
2193# server.setblocking(False)
2194# client.setblocking(False)
2195# while server.renegotiate_pending():
2196# client.do_handshake()
2197# server.do_handshake()
2198
2199# self.assertEquals(server.total_renegotiations(), 1)
2200
2201
2202
2203
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002204class ErrorTests(TestCase):
2205 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002206 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002207 """
2208 def test_type(self):
2209 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002210 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002211 """
2212 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05002213 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05002214
2215
2216
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002217class ConstantsTests(TestCase):
2218 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002219 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002220
2221 These are values defined by OpenSSL intended only to be used as flags to
2222 OpenSSL APIs. The only assertions it seems can be made about them is
2223 their values.
2224 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002225 # unittest.TestCase has no skip mechanism
2226 if OP_NO_QUERY_MTU is not None:
2227 def test_op_no_query_mtu(self):
2228 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002229 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002230 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002231 """
2232 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
2233 else:
2234 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002235
2236
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002237 if OP_COOKIE_EXCHANGE is not None:
2238 def test_op_cookie_exchange(self):
2239 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002240 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002241 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002242 """
2243 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
2244 else:
2245 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002246
2247
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002248 if OP_NO_TICKET is not None:
2249 def test_op_no_ticket(self):
2250 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002251 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002252 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002253 """
2254 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04002255 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002256 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05002257
2258
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002259 if OP_NO_COMPRESSION is not None:
2260 def test_op_no_compression(self):
2261 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002262 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
2263 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002264 """
2265 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
2266 else:
2267 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
2268
2269
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002270 def test_sess_cache_off(self):
2271 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002272 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
2273 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002274 """
2275 self.assertEqual(0x0, SESS_CACHE_OFF)
2276
2277
2278 def test_sess_cache_client(self):
2279 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002280 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
2281 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002282 """
2283 self.assertEqual(0x1, SESS_CACHE_CLIENT)
2284
2285
2286 def test_sess_cache_server(self):
2287 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002288 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
2289 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002290 """
2291 self.assertEqual(0x2, SESS_CACHE_SERVER)
2292
2293
2294 def test_sess_cache_both(self):
2295 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002296 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
2297 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002298 """
2299 self.assertEqual(0x3, SESS_CACHE_BOTH)
2300
2301
2302 def test_sess_cache_no_auto_clear(self):
2303 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002304 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
2305 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
2306 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002307 """
2308 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
2309
2310
2311 def test_sess_cache_no_internal_lookup(self):
2312 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002313 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
2314 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
2315 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002316 """
2317 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
2318
2319
2320 def test_sess_cache_no_internal_store(self):
2321 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002322 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
2323 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
2324 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002325 """
2326 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
2327
2328
2329 def test_sess_cache_no_internal(self):
2330 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002331 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
2332 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
2333 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002334 """
2335 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
2336
2337
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04002338
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002339class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05002340 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002341 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05002342 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002343 def _server(self, sock):
2344 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002345 Create a new server-side SSL :py:obj:`Connection` object wrapped around
2346 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002347 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002348 # Create the server side Connection. This is mostly setup boilerplate
2349 # - use TLSv1, use a particular certificate, etc.
2350 server_ctx = Context(TLSv1_METHOD)
2351 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2352 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2353 server_store = server_ctx.get_cert_store()
2354 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2355 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2356 server_ctx.check_privatekey()
2357 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002358 # Here the Connection is actually created. If None is passed as the 2nd
2359 # parameter, it indicates a memory BIO should be created.
2360 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002361 server_conn.set_accept_state()
2362 return server_conn
2363
2364
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002365 def _client(self, sock):
2366 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002367 Create a new client-side SSL :py:obj:`Connection` object wrapped around
2368 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002369 """
2370 # Now create the client side Connection. Similar boilerplate to the
2371 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002372 client_ctx = Context(TLSv1_METHOD)
2373 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2374 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2375 client_store = client_ctx.get_cert_store()
2376 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
2377 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
2378 client_ctx.check_privatekey()
2379 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002380 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002381 client_conn.set_connect_state()
2382 return client_conn
2383
2384
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002385 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002386 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002387 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002388 reading from the output of each and writing those bytes to the input of
2389 the other and in this way establish a connection and exchange
2390 application-level bytes with each other.
2391 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002392 server_conn = self._server(None)
2393 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002394
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002395 # There should be no key or nonces yet.
2396 self.assertIdentical(server_conn.master_key(), None)
2397 self.assertIdentical(server_conn.client_random(), None)
2398 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002399
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002400 # First, the handshake needs to happen. We'll deliver bytes back and
2401 # forth between the client and server until neither of them feels like
2402 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002403 self.assertIdentical(
2404 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002405
2406 # Now that the handshake is done, there should be a key and nonces.
2407 self.assertNotIdentical(server_conn.master_key(), None)
2408 self.assertNotIdentical(server_conn.client_random(), None)
2409 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04002410 self.assertEquals(server_conn.client_random(), client_conn.client_random())
2411 self.assertEquals(server_conn.server_random(), client_conn.server_random())
2412 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
2413 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002414
2415 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002416 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05002417
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002418 server_conn.write(important_message)
2419 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002420 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002421 (client_conn, important_message))
2422
2423 client_conn.write(important_message[::-1])
2424 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002425 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002426 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05002427
2428
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002429 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05002430 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002431 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002432
2433 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09002434 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002435 this test fails, there must be a problem outside the memory BIO
2436 code, as no memory BIO is involved here). Even though this isn't a
2437 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05002438 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04002439 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05002440
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002441 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05002442 client_conn.send(important_message)
2443 msg = server_conn.recv(1024)
2444 self.assertEqual(msg, important_message)
2445
2446 # Again in the other direction, just for fun.
2447 important_message = important_message[::-1]
2448 server_conn.send(important_message)
2449 msg = client_conn.recv(1024)
2450 self.assertEqual(msg, important_message)
2451
2452
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04002453 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05002454 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002455 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
2456 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05002457 """
2458 context = Context(SSLv3_METHOD)
2459 client = socket()
2460 clientSSL = Connection(context, client)
2461 self.assertRaises( TypeError, clientSSL.bio_read, 100)
2462 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04002463 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002464
2465
2466 def test_outgoingOverflow(self):
2467 """
2468 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002469 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002470 returned and that many bytes from the beginning of the input can be
2471 read from the other end of the connection.
2472 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002473 server = self._server(None)
2474 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002475
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002476 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002477
2478 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002479 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002480 # Sanity check. We're trying to test what happens when the entire
2481 # input can't be sent. If the entire input was sent, this test is
2482 # meaningless.
2483 self.assertTrue(sent < size)
2484
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002485 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002486 self.assertIdentical(receiver, server)
2487
2488 # We can rely on all of these bytes being received at once because
2489 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
2490 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002491
2492
2493 def test_shutdown(self):
2494 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002495 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
2496 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002497 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002498 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002499 server.bio_shutdown()
2500 e = self.assertRaises(Error, server.recv, 1024)
2501 # We don't want WantReadError or ZeroReturnError or anything - it's a
2502 # handshake failure.
2503 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002504
2505
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002506 def test_unexpectedEndOfFile(self):
2507 """
2508 If the connection is lost before an orderly SSL shutdown occurs,
2509 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
2510 "Unexpected EOF".
2511 """
2512 server_conn, client_conn = self._loopback()
2513 client_conn.sock_shutdown(SHUT_RDWR)
2514 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
2515 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
2516
2517
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002518 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002519 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002520 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 -04002521
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002522 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002523 before the client and server are connected to each other. This
2524 function should specify a list of CAs for the server to send to the
2525 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09002526 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002527 times.
2528 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002529 server = self._server(None)
2530 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002531 self.assertEqual(client.get_client_ca_list(), [])
2532 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002533 ctx = server.get_context()
2534 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002535 self.assertEqual(client.get_client_ca_list(), [])
2536 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002537 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002538 self.assertEqual(client.get_client_ca_list(), expected)
2539 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002540
2541
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002542 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002543 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002544 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002545 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002546 """
2547 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002548 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
2549 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
2550 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002551
2552
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002553 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002554 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002555 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002556 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09002557 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002558 after the connection is set up.
2559 """
2560 def no_ca(ctx):
2561 ctx.set_client_ca_list([])
2562 return []
2563 self._check_client_ca_list(no_ca)
2564
2565
2566 def test_set_one_ca_list(self):
2567 """
2568 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002569 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002570 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002571 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002572 X509Name after the connection is set up.
2573 """
2574 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2575 cadesc = cacert.get_subject()
2576 def single_ca(ctx):
2577 ctx.set_client_ca_list([cadesc])
2578 return [cadesc]
2579 self._check_client_ca_list(single_ca)
2580
2581
2582 def test_set_multiple_ca_list(self):
2583 """
2584 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002585 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002586 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002587 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002588 X509Names after the connection is set up.
2589 """
2590 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2591 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2592
2593 sedesc = secert.get_subject()
2594 cldesc = clcert.get_subject()
2595
2596 def multiple_ca(ctx):
2597 L = [sedesc, cldesc]
2598 ctx.set_client_ca_list(L)
2599 return L
2600 self._check_client_ca_list(multiple_ca)
2601
2602
2603 def test_reset_ca_list(self):
2604 """
2605 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09002606 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002607 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002608 """
2609 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2610 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2611 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2612
2613 cadesc = cacert.get_subject()
2614 sedesc = secert.get_subject()
2615 cldesc = clcert.get_subject()
2616
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002617 def changed_ca(ctx):
2618 ctx.set_client_ca_list([sedesc, cldesc])
2619 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002620 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002621 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002622
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002623
2624 def test_mutated_ca_list(self):
2625 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002626 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002627 afterwards, this does not affect the list of CA names sent to the
2628 client.
2629 """
2630 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2631 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2632
2633 cadesc = cacert.get_subject()
2634 sedesc = secert.get_subject()
2635
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002636 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002637 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002638 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002639 L.append(sedesc)
2640 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002641 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002642
2643
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002644 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002645 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002646 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002647 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002648 """
2649 ctx = Context(TLSv1_METHOD)
2650 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002651 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002652 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002653 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002654
2655
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002656 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002657 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002658 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09002659 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002660 """
2661 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2662 cadesc = cacert.get_subject()
2663 def single_ca(ctx):
2664 ctx.add_client_ca(cacert)
2665 return [cadesc]
2666 self._check_client_ca_list(single_ca)
2667
2668
2669 def test_multiple_add_client_ca(self):
2670 """
2671 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09002672 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002673 """
2674 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2675 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2676
2677 cadesc = cacert.get_subject()
2678 sedesc = secert.get_subject()
2679
2680 def multiple_ca(ctx):
2681 ctx.add_client_ca(cacert)
2682 ctx.add_client_ca(secert)
2683 return [cadesc, sedesc]
2684 self._check_client_ca_list(multiple_ca)
2685
2686
2687 def test_set_and_add_client_ca(self):
2688 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002689 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
2690 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002691 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002692 """
2693 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2694 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2695 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2696
2697 cadesc = cacert.get_subject()
2698 sedesc = secert.get_subject()
2699 cldesc = clcert.get_subject()
2700
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002701 def mixed_set_add_ca(ctx):
2702 ctx.set_client_ca_list([cadesc, sedesc])
2703 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002704 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002705 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002706
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002707
2708 def test_set_after_add_client_ca(self):
2709 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002710 A call to :py:obj:`Context.set_client_ca_list` after a call to
2711 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002712 call with the names specified by the latter cal.
2713 """
2714 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2715 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2716 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2717
2718 cadesc = cacert.get_subject()
2719 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002720
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002721 def set_replaces_add_ca(ctx):
2722 ctx.add_client_ca(clcert)
2723 ctx.set_client_ca_list([cadesc])
2724 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002725 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002726 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002727
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002728
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002729
2730class ConnectionBIOTests(TestCase):
2731 """
2732 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
2733 """
2734 def test_wantReadError(self):
2735 """
2736 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
2737 if there are no bytes available to be read from the BIO.
2738 """
2739 ctx = Context(TLSv1_METHOD)
2740 conn = Connection(ctx, None)
2741 self.assertRaises(WantReadError, conn.bio_read, 1024)
2742
2743
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002744 def test_buffer_size(self):
2745 """
2746 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
2747 number of bytes to read and return.
2748 """
2749 ctx = Context(TLSv1_METHOD)
2750 conn = Connection(ctx, None)
2751 conn.set_connect_state()
2752 try:
2753 conn.do_handshake()
2754 except WantReadError:
2755 pass
2756 data = conn.bio_read(2)
2757 self.assertEqual(2, len(data))
2758
2759
2760 if not PY3:
2761 def test_buffer_size_long(self):
2762 """
2763 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
2764 :py:obj:`long` as well as :py:obj:`int`.
2765 """
2766 ctx = Context(TLSv1_METHOD)
2767 conn = Connection(ctx, None)
2768 conn.set_connect_state()
2769 try:
2770 conn.do_handshake()
2771 except WantReadError:
2772 pass
2773 data = conn.bio_read(long(2))
2774 self.assertEqual(2, len(data))
2775
2776
2777
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002778
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04002779class InfoConstantTests(TestCase):
2780 """
2781 Tests for assorted constants exposed for use in info callbacks.
2782 """
2783 def test_integers(self):
2784 """
2785 All of the info constants are integers.
2786
2787 This is a very weak test. It would be nice to have one that actually
2788 verifies that as certain info events happen, the value passed to the
2789 info callback matches up with the constant exposed by OpenSSL.SSL.
2790 """
2791 for const in [
2792 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
2793 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
2794 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
2795 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
2796 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
2797 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
2798
2799 self.assertTrue(isinstance(const, int))
2800
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02002801
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002802if __name__ == '__main__':
2803 main()