blob: 95cb538b48dbd5888d3723b67e22bf181432e9c3 [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
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08009from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE
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 Calderone20222ae2011-05-19 21:43:46 -040017from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080018from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040019from OpenSSL.crypto import dump_privatekey, load_privatekey
20from OpenSSL.crypto import dump_certificate, load_certificate
21
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040022from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
23from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040024from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040025from OpenSSL.SSL import (
26 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
27 TLSv1_1_METHOD, TLSv1_2_METHOD)
28from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040029from OpenSSL.SSL import (
30 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040031
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040032from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050033 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
34 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
35 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
36
37from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070038 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050039from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070040 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040041
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050042from OpenSSL.test.util import TestCase, b
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040043from OpenSSL.test.test_crypto import (
44 cleartextCertificatePEM, cleartextPrivateKeyPEM)
45from OpenSSL.test.test_crypto import (
46 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
47 root_cert_pem)
48
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050049try:
50 from OpenSSL.SSL import OP_NO_QUERY_MTU
51except ImportError:
52 OP_NO_QUERY_MTU = None
53try:
54 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
55except ImportError:
56 OP_COOKIE_EXCHANGE = None
57try:
58 from OpenSSL.SSL import OP_NO_TICKET
59except ImportError:
60 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040061
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040062try:
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -040063 from OpenSSL.SSL import OP_NO_COMPRESSION
64except ImportError:
65 OP_NO_COMPRESSION = None
66
67try:
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040068 from OpenSSL.SSL import MODE_RELEASE_BUFFERS
69except ImportError:
70 MODE_RELEASE_BUFFERS = None
71
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040072try:
73 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
74except ImportError:
75 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
76
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040077from OpenSSL.SSL import (
78 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
79 SSL_ST_OK, SSL_ST_RENEGOTIATE,
80 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
81 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
82 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
83 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040084
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040085# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
86# to use)
87dhparam = """\
88-----BEGIN DH PARAMETERS-----
89MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
90-----END DH PARAMETERS-----
91"""
92
93
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040094def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040095 return ok
96
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040097
Rick Deanb1ccd562009-07-09 23:52:39 -050098def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040099 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400100 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400101 """
102 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500103 port = socket()
104 port.bind(('', 0))
105 port.listen(1)
106 client = socket()
107 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400108 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400109 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500110 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500111
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400112 # Let's pass some unencrypted data to make sure our socket connection is
113 # fine. Just one byte, so we don't have to worry about buffers getting
114 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400115 server.send(b("x"))
116 assert client.recv(1024) == b("x")
117 client.send(b("y"))
118 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500119
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400120 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400121 server.setblocking(False)
122 client.setblocking(False)
123
Rick Deanb1ccd562009-07-09 23:52:39 -0500124 return (server, client)
125
126
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400127
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400128def handshake(client, server):
129 conns = [client, server]
130 while conns:
131 for conn in conns:
132 try:
133 conn.do_handshake()
134 except WantReadError:
135 pass
136 else:
137 conns.remove(conn)
138
139
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400140def _create_certificate_chain():
141 """
142 Construct and return a chain of certificates.
143
144 1. A new self-signed certificate authority certificate (cacert)
145 2. A new intermediate certificate signed by cacert (icert)
146 3. A new server certificate signed by icert (scert)
147 """
148 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
149
150 # Step 1
151 cakey = PKey()
152 cakey.generate_key(TYPE_RSA, 512)
153 cacert = X509()
154 cacert.get_subject().commonName = "Authority Certificate"
155 cacert.set_issuer(cacert.get_subject())
156 cacert.set_pubkey(cakey)
157 cacert.set_notBefore(b("20000101000000Z"))
158 cacert.set_notAfter(b("20200101000000Z"))
159 cacert.add_extensions([caext])
160 cacert.set_serial_number(0)
161 cacert.sign(cakey, "sha1")
162
163 # Step 2
164 ikey = PKey()
165 ikey.generate_key(TYPE_RSA, 512)
166 icert = X509()
167 icert.get_subject().commonName = "Intermediate Certificate"
168 icert.set_issuer(cacert.get_subject())
169 icert.set_pubkey(ikey)
170 icert.set_notBefore(b("20000101000000Z"))
171 icert.set_notAfter(b("20200101000000Z"))
172 icert.add_extensions([caext])
173 icert.set_serial_number(0)
174 icert.sign(cakey, "sha1")
175
176 # Step 3
177 skey = PKey()
178 skey.generate_key(TYPE_RSA, 512)
179 scert = X509()
180 scert.get_subject().commonName = "Server Certificate"
181 scert.set_issuer(icert.get_subject())
182 scert.set_pubkey(skey)
183 scert.set_notBefore(b("20000101000000Z"))
184 scert.set_notAfter(b("20200101000000Z"))
185 scert.add_extensions([
186 X509Extension(b('basicConstraints'), True, b('CA:false'))])
187 scert.set_serial_number(0)
188 scert.sign(ikey, "sha1")
189
190 return [(cakey, cacert), (ikey, icert), (skey, scert)]
191
192
193
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400194class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400195 """
196 Helper mixin which defines methods for creating a connected socket pair and
197 for forcing two connected SSL sockets to talk to each other via memory BIOs.
198 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500199 def _loopbackClientFactory(self, socket):
200 client = Connection(Context(TLSv1_METHOD), socket)
201 client.set_connect_state()
202 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400203
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500204
205 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400206 ctx = Context(TLSv1_METHOD)
207 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
208 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500209 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400210 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500211 return server
212
213
214 def _loopback(self, serverFactory=None, clientFactory=None):
215 if serverFactory is None:
216 serverFactory = self._loopbackServerFactory
217 if clientFactory is None:
218 clientFactory = self._loopbackClientFactory
219
220 (server, client) = socket_pair()
221 server = serverFactory(server)
222 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400223
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400224 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400225
226 server.setblocking(True)
227 client.setblocking(True)
228 return server, client
229
230
231 def _interactInMemory(self, client_conn, server_conn):
232 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900233 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400234 objects. Copy bytes back and forth between their send/receive buffers
235 for as long as there is anything to copy. When there is nothing more
Jonathan Ballet648875f2011-07-16 14:14:58 +0900236 to copy, return :py:obj:`None`. If one of them actually manages to deliver
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400237 some application bytes, return a two-tuple of the connection from which
238 the bytes were read and the bytes themselves.
239 """
240 wrote = True
241 while wrote:
242 # Loop until neither side has anything to say
243 wrote = False
244
245 # Copy stuff from each side's send buffer to the other side's
246 # receive buffer.
247 for (read, write) in [(client_conn, server_conn),
248 (server_conn, client_conn)]:
249
250 # Give the side a chance to generate some more bytes, or
251 # succeed.
252 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400253 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400254 except WantReadError:
255 # It didn't succeed, so we'll hope it generated some
256 # output.
257 pass
258 else:
259 # It did succeed, so we'll stop now and let the caller deal
260 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400261 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400262
263 while True:
264 # Keep copying as long as there's more stuff there.
265 try:
266 dirty = read.bio_read(4096)
267 except WantReadError:
268 # Okay, nothing more waiting to be sent. Stop
269 # processing this send buffer.
270 break
271 else:
272 # Keep track of the fact that someone generated some
273 # output.
274 wrote = True
275 write.bio_write(dirty)
276
277
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400278
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400279class VersionTests(TestCase):
280 """
281 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900282 :py:obj:`OpenSSL.SSL.SSLeay_version` and
283 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400284 """
285 def test_OPENSSL_VERSION_NUMBER(self):
286 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900287 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400288 byte and the patch, fix, minor, and major versions in the
289 nibbles above that.
290 """
291 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
292
293
294 def test_SSLeay_version(self):
295 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900296 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400297 one of a number of version strings based on that indicator.
298 """
299 versions = {}
300 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
301 SSLEAY_PLATFORM, SSLEAY_DIR]:
302 version = SSLeay_version(t)
303 versions[version] = t
304 self.assertTrue(isinstance(version, bytes))
305 self.assertEqual(len(versions), 5)
306
307
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400308
309class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400310 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900311 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400312 """
313 def test_method(self):
314 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900315 :py:obj:`Context` can be instantiated with one of :py:obj:`SSLv2_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400316 :py:obj:`SSLv3_METHOD`, :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
317 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400318 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400319 methods = [
320 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
321 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400322 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400323
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400324
325 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
326 for meth in maybe:
327 try:
328 Context(meth)
329 except (Error, ValueError):
330 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
331 # don't. Difficult to say in advance.
332 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400333
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400334 self.assertRaises(TypeError, Context, "")
335 self.assertRaises(ValueError, Context, 10)
336
337
Rick Deane15b1472009-07-09 15:53:42 -0500338 def test_type(self):
339 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900340 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400341 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500342 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400343 self.assertIdentical(Context, ContextType)
344 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500345
346
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400347 def test_use_privatekey(self):
348 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900349 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400350 """
351 key = PKey()
352 key.generate_key(TYPE_RSA, 128)
353 ctx = Context(TLSv1_METHOD)
354 ctx.use_privatekey(key)
355 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400356
357
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800358 def test_use_privatekey_file_missing(self):
359 """
360 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error`
361 when passed the name of a file which does not exist.
362 """
363 ctx = Context(TLSv1_METHOD)
364 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
365
366
367 def test_use_certificate_wrong_args(self):
368 """
369 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
370 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as an
371 argument.
372 """
373 ctx = Context(TLSv1_METHOD)
374 self.assertRaises(TypeError, ctx.use_certificate)
375 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
376 self.assertRaises(TypeError, ctx.use_certificate, X509(), "hello, world")
377
378
379 def test_use_certificate_uninitialized(self):
380 """
381 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
382 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
383 initialized (ie, which does not actually have any certificate data).
384 """
385 ctx = Context(TLSv1_METHOD)
386 self.assertRaises(Error, ctx.use_certificate, X509())
387
388
389 def test_use_certificate(self):
390 """
391 :py:obj:`Context.use_certificate` sets the certificate which will be
392 used to identify connections created using the context.
393 """
394 # TODO
395 # Hard to assert anything. But we could set a privatekey then ask
396 # OpenSSL if the cert and key agree using check_privatekey. Then as
397 # long as check_privatekey works right we're good...
398 ctx = Context(TLSv1_METHOD)
399 ctx.use_certificate(load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
400
401
402 def test_use_certificate_file_wrong_args(self):
403 """
404 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
405 called with zero arguments or more than two arguments, or if the first
406 argument is not a byte string or the second argumnent is not an integer.
407 """
408 ctx = Context(TLSv1_METHOD)
409 self.assertRaises(TypeError, ctx.use_certificate_file)
410 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile", object())
411 self.assertRaises(
412 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM, object())
413 self.assertRaises(
414 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
415 self.assertRaises(
416 TypeError, ctx.use_certificate_file, b"somefile", object())
417
418
419 def test_use_certificate_file_missing(self):
420 """
421 :py:obj:`Context.use_certificate_file` raises
422 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does not
423 exist.
424 """
425 ctx = Context(TLSv1_METHOD)
426 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
427
428
429 def test_use_certificate_file(self):
430 """
431 :py:obj:`Context.use_certificate` sets the certificate which will be
432 used to identify connections created using the context.
433 """
434 # TODO
435 # Hard to assert anything. But we could set a privatekey then ask
436 # OpenSSL if the cert and key agree using check_privatekey. Then as
437 # long as check_privatekey works right we're good...
438 pem_filename = self.mktemp()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500439 with open(pem_filename, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800440 pem_file.write(cleartextCertificatePEM)
441
442 ctx = Context(TLSv1_METHOD)
443 ctx.use_certificate_file(pem_filename)
444
445
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400446 def test_set_app_data_wrong_args(self):
447 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900448 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called with other than
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400449 one argument.
450 """
451 context = Context(TLSv1_METHOD)
452 self.assertRaises(TypeError, context.set_app_data)
453 self.assertRaises(TypeError, context.set_app_data, None, None)
454
455
456 def test_get_app_data_wrong_args(self):
457 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900458 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400459 arguments.
460 """
461 context = Context(TLSv1_METHOD)
462 self.assertRaises(TypeError, context.get_app_data, None)
463
464
465 def test_app_data(self):
466 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900467 :py:obj:`Context.set_app_data` stores an object for later retrieval using
468 :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400469 """
470 app_data = object()
471 context = Context(TLSv1_METHOD)
472 context.set_app_data(app_data)
473 self.assertIdentical(context.get_app_data(), app_data)
474
475
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400476 def test_set_options_wrong_args(self):
477 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900478 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with the wrong
479 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400480 """
481 context = Context(TLSv1_METHOD)
482 self.assertRaises(TypeError, context.set_options)
483 self.assertRaises(TypeError, context.set_options, None)
484 self.assertRaises(TypeError, context.set_options, 1, None)
485
486
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300487 def test_set_mode_wrong_args(self):
488 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400489 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with the wrong
490 number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300491 """
492 context = Context(TLSv1_METHOD)
493 self.assertRaises(TypeError, context.set_mode)
494 self.assertRaises(TypeError, context.set_mode, None)
495 self.assertRaises(TypeError, context.set_mode, 1, None)
496
497
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400498 if MODE_RELEASE_BUFFERS is not None:
499 def test_set_mode(self):
500 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400501 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the newly
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400502 set mode.
503 """
504 context = Context(TLSv1_METHOD)
505 self.assertTrue(
506 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
507 else:
508 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
509
510
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400511 def test_set_timeout_wrong_args(self):
512 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900513 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with the wrong
514 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400515 """
516 context = Context(TLSv1_METHOD)
517 self.assertRaises(TypeError, context.set_timeout)
518 self.assertRaises(TypeError, context.set_timeout, None)
519 self.assertRaises(TypeError, context.set_timeout, 1, None)
520
521
522 def test_get_timeout_wrong_args(self):
523 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900524 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400525 """
526 context = Context(TLSv1_METHOD)
527 self.assertRaises(TypeError, context.get_timeout, None)
528
529
530 def test_timeout(self):
531 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900532 :py:obj:`Context.set_timeout` sets the session timeout for all connections
533 created using the context object. :py:obj:`Context.get_timeout` retrieves this
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400534 value.
535 """
536 context = Context(TLSv1_METHOD)
537 context.set_timeout(1234)
538 self.assertEquals(context.get_timeout(), 1234)
539
540
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400541 def test_set_verify_depth_wrong_args(self):
542 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900543 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called with the wrong
544 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400545 """
546 context = Context(TLSv1_METHOD)
547 self.assertRaises(TypeError, context.set_verify_depth)
548 self.assertRaises(TypeError, context.set_verify_depth, None)
549 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
550
551
552 def test_get_verify_depth_wrong_args(self):
553 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900554 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400555 """
556 context = Context(TLSv1_METHOD)
557 self.assertRaises(TypeError, context.get_verify_depth, None)
558
559
560 def test_verify_depth(self):
561 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900562 :py:obj:`Context.set_verify_depth` sets the number of certificates in a chain
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400563 to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900564 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400565 """
566 context = Context(TLSv1_METHOD)
567 context.set_verify_depth(11)
568 self.assertEquals(context.get_verify_depth(), 11)
569
570
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400571 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400572 """
573 Write a new private key out to a new file, encrypted using the given
574 passphrase. Return the path to the new file.
575 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400576 key = PKey()
577 key.generate_key(TYPE_RSA, 128)
578 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400579 fObj = open(pemFile, 'w')
580 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
581 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400582 fObj.close()
583 return pemFile
584
585
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400586 def test_set_passwd_cb_wrong_args(self):
587 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900588 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called with the
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400589 wrong arguments or with a non-callable first argument.
590 """
591 context = Context(TLSv1_METHOD)
592 self.assertRaises(TypeError, context.set_passwd_cb)
593 self.assertRaises(TypeError, context.set_passwd_cb, None)
594 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
595
596
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400597 def test_set_passwd_cb(self):
598 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900599 :py:obj:`Context.set_passwd_cb` accepts a callable which will be invoked when
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400600 a private key is loaded from an encrypted PEM.
601 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400602 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400603 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400604 calledWith = []
605 def passphraseCallback(maxlen, verify, extra):
606 calledWith.append((maxlen, verify, extra))
607 return passphrase
608 context = Context(TLSv1_METHOD)
609 context.set_passwd_cb(passphraseCallback)
610 context.use_privatekey_file(pemFile)
611 self.assertTrue(len(calledWith), 1)
612 self.assertTrue(isinstance(calledWith[0][0], int))
613 self.assertTrue(isinstance(calledWith[0][1], int))
614 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400615
616
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400617 def test_passwd_callback_exception(self):
618 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900619 :py:obj:`Context.use_privatekey_file` propagates any exception raised by the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400620 passphrase callback.
621 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400622 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400623 def passphraseCallback(maxlen, verify, extra):
624 raise RuntimeError("Sorry, I am a fail.")
625
626 context = Context(TLSv1_METHOD)
627 context.set_passwd_cb(passphraseCallback)
628 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
629
630
631 def test_passwd_callback_false(self):
632 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900633 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400634 passphrase callback returns a false value.
635 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400636 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400637 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500638 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400639
640 context = Context(TLSv1_METHOD)
641 context.set_passwd_cb(passphraseCallback)
642 self.assertRaises(Error, context.use_privatekey_file, pemFile)
643
644
645 def test_passwd_callback_non_string(self):
646 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900647 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400648 passphrase callback returns a true non-string value.
649 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400650 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400651 def passphraseCallback(maxlen, verify, extra):
652 return 10
653
654 context = Context(TLSv1_METHOD)
655 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800656 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400657
658
659 def test_passwd_callback_too_long(self):
660 """
661 If the passphrase returned by the passphrase callback returns a string
662 longer than the indicated maximum length, it is truncated.
663 """
664 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400665 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400666 pemFile = self._write_encrypted_pem(passphrase)
667 def passphraseCallback(maxlen, verify, extra):
668 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400669 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400670
671 context = Context(TLSv1_METHOD)
672 context.set_passwd_cb(passphraseCallback)
673 # This shall succeed because the truncated result is the correct
674 # passphrase.
675 context.use_privatekey_file(pemFile)
676
677
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400678 def test_set_info_callback(self):
679 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900680 :py:obj:`Context.set_info_callback` accepts a callable which will be invoked
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400681 when certain information about an SSL connection is available.
682 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500683 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400684
685 clientSSL = Connection(Context(TLSv1_METHOD), client)
686 clientSSL.set_connect_state()
687
688 called = []
689 def info(conn, where, ret):
690 called.append((conn, where, ret))
691 context = Context(TLSv1_METHOD)
692 context.set_info_callback(info)
693 context.use_certificate(
694 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
695 context.use_privatekey(
696 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
697
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400698 serverSSL = Connection(context, server)
699 serverSSL.set_accept_state()
700
701 while not called:
702 for ssl in clientSSL, serverSSL:
703 try:
704 ssl.do_handshake()
705 except WantReadError:
706 pass
707
708 # Kind of lame. Just make sure it got called somehow.
709 self.assertTrue(called)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400710
711
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400712 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400713 """
714 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400715 its :py:obj:`load_verify_locations` method with the given arguments.
716 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400717 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500718 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400719
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400720 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400721 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400722 # Require that the server certificate verify properly or the
723 # connection will fail.
724 clientContext.set_verify(
725 VERIFY_PEER,
726 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
727
728 clientSSL = Connection(clientContext, client)
729 clientSSL.set_connect_state()
730
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400731 serverContext = Context(TLSv1_METHOD)
732 serverContext.use_certificate(
733 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
734 serverContext.use_privatekey(
735 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
736
737 serverSSL = Connection(serverContext, server)
738 serverSSL.set_accept_state()
739
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400740 # Without load_verify_locations above, the handshake
741 # will fail:
742 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
743 # 'certificate verify failed')]
744 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400745
746 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400747 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400748
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500749
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400750 def test_load_verify_file(self):
751 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900752 :py:obj:`Context.load_verify_locations` accepts a file name and uses the
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400753 certificates within for verification purposes.
754 """
755 cafile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400756 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400757 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400758 fObj.close()
759
760 self._load_verify_locations_test(cafile)
761
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400762
763 def test_load_verify_invalid_file(self):
764 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900765 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when passed a
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400766 non-existent cafile.
767 """
768 clientContext = Context(TLSv1_METHOD)
769 self.assertRaises(
770 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400771
772
773 def test_load_verify_directory(self):
774 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900775 :py:obj:`Context.load_verify_locations` accepts a directory name and uses
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400776 the certificates within for verification purposes.
777 """
778 capath = self.mktemp()
779 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400780 # Hash values computed manually with c_rehash to avoid depending on
781 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
782 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500783 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400784 cafile = join(capath, name)
785 fObj = open(cafile, 'w')
786 fObj.write(cleartextCertificatePEM.decode('ascii'))
787 fObj.close()
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400788
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400789 self._load_verify_locations_test(None, capath)
790
791
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400792 def test_load_verify_locations_wrong_args(self):
793 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900794 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if called with
795 the wrong number of arguments or with non-:py:obj:`str` arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400796 """
797 context = Context(TLSv1_METHOD)
798 self.assertRaises(TypeError, context.load_verify_locations)
799 self.assertRaises(TypeError, context.load_verify_locations, object())
800 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
801 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
802
803
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400804 if platform == "win32":
805 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400806 "See LP#404343 and LP#404344."
807 else:
808 def test_set_default_verify_paths(self):
809 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900810 :py:obj:`Context.set_default_verify_paths` causes the platform-specific CA
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400811 certificate locations to be used for verification purposes.
812 """
813 # Testing this requires a server with a certificate signed by one of
814 # the CAs in the platform CA location. Getting one of those costs
815 # money. Fortunately (or unfortunately, depending on your
816 # perspective), it's easy to think of a public server on the
817 # internet which has such a certificate. Connecting to the network
818 # in a unit test is bad, but it's the only way I can think of to
819 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400820
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400821 # Arg, verisign.com doesn't speak TLSv1
822 context = Context(SSLv3_METHOD)
823 context.set_default_verify_paths()
824 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +0200825 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400826 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400827
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400828 client = socket()
829 client.connect(('verisign.com', 443))
830 clientSSL = Connection(context, client)
831 clientSSL.set_connect_state()
832 clientSSL.do_handshake()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500833 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400834 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400835
836
837 def test_set_default_verify_paths_signature(self):
838 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900839 :py:obj:`Context.set_default_verify_paths` takes no arguments and raises
840 :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400841 """
842 context = Context(TLSv1_METHOD)
843 self.assertRaises(TypeError, context.set_default_verify_paths, None)
844 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
845 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500846
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400847
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500848 def test_add_extra_chain_cert_invalid_cert(self):
849 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900850 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if called with
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500851 other than one argument or if called with an object which is not an
Jonathan Ballet648875f2011-07-16 14:14:58 +0900852 instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500853 """
854 context = Context(TLSv1_METHOD)
855 self.assertRaises(TypeError, context.add_extra_chain_cert)
856 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
857 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
858
859
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400860 def _handshake_test(self, serverContext, clientContext):
861 """
862 Verify that a client and server created with the given contexts can
863 successfully handshake and communicate.
864 """
865 serverSocket, clientSocket = socket_pair()
866
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400867 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400868 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400869
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400870 client = Connection(clientContext, clientSocket)
871 client.set_connect_state()
872
873 # Make them talk to each other.
874 # self._interactInMemory(client, server)
875 for i in range(3):
876 for s in [client, server]:
877 try:
878 s.do_handshake()
879 except WantReadError:
880 pass
881
882
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800883 def test_set_verify_callback_exception(self):
884 """
885 If the verify callback passed to :py:obj:`Context.set_verify` raises an
886 exception, verification fails and the exception is propagated to the
887 caller of :py:obj:`Connection.do_handshake`.
888 """
889 serverContext = Context(TLSv1_METHOD)
890 serverContext.use_privatekey(
891 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
892 serverContext.use_certificate(
893 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
894
895 clientContext = Context(TLSv1_METHOD)
896 def verify_callback(*args):
897 raise Exception("silly verify failure")
898 clientContext.set_verify(VERIFY_PEER, verify_callback)
899
900 exc = self.assertRaises(
901 Exception, self._handshake_test, serverContext, clientContext)
902 self.assertEqual("silly verify failure", str(exc))
903
904
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400905 def test_add_extra_chain_cert(self):
906 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900907 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509` instance to add to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400908 the certificate chain.
909
Jonathan Ballet648875f2011-07-16 14:14:58 +0900910 See :py:obj:`_create_certificate_chain` for the details of the certificate
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400911 chain tested.
912
913 The chain is tested by starting a server with scert and connecting
914 to it with a client which trusts cacert and requires verification to
915 succeed.
916 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400917 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400918 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
919
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400920 # Dump the CA certificate to a file because that's the only way to load
921 # it as a trusted CA in the client context.
922 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400923 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400924 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400925 fObj.close()
926
927 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400928 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400929 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400930 fObj.close()
931
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400932 # Create the server context
933 serverContext = Context(TLSv1_METHOD)
934 serverContext.use_privatekey(skey)
935 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400936 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400937 serverContext.add_extra_chain_cert(icert)
938
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400939 # Create the client
940 clientContext = Context(TLSv1_METHOD)
941 clientContext.set_verify(
942 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500943 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400944
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400945 # Try it out.
946 self._handshake_test(serverContext, clientContext)
947
948
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400949 def test_use_certificate_chain_file(self):
950 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900951 :py:obj:`Context.use_certificate_chain_file` reads a certificate chain from
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400952 the specified file.
953
954 The chain is tested by starting a server with scert and connecting
955 to it with a client which trusts cacert and requires verification to
956 succeed.
957 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400958 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400959 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
960
961 # Write out the chain file.
962 chainFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400963 fObj = open(chainFile, 'w')
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400964 # Most specific to least general.
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400965 fObj.write(dump_certificate(FILETYPE_PEM, scert).decode('ascii'))
966 fObj.write(dump_certificate(FILETYPE_PEM, icert).decode('ascii'))
967 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400968 fObj.close()
969
970 serverContext = Context(TLSv1_METHOD)
971 serverContext.use_certificate_chain_file(chainFile)
972 serverContext.use_privatekey(skey)
973
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400974 fObj = open('ca.pem', 'w')
975 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400976 fObj.close()
977
978 clientContext = Context(TLSv1_METHOD)
979 clientContext.set_verify(
980 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500981 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400982
983 self._handshake_test(serverContext, clientContext)
984
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800985
986 def test_use_certificate_chain_file_wrong_args(self):
987 """
988 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
989 if passed zero or more than one argument or when passed a non-byte
990 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error` when
991 passed a bad chain file name (for example, the name of a file which does
992 not exist).
993 """
994 context = Context(TLSv1_METHOD)
995 self.assertRaises(TypeError, context.use_certificate_chain_file)
996 self.assertRaises(TypeError, context.use_certificate_chain_file, object())
997 self.assertRaises(TypeError, context.use_certificate_chain_file, b"foo", object())
998
999 self.assertRaises(Error, context.use_certificate_chain_file, self.mktemp())
1000
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001001 # XXX load_client_ca
1002 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001003
1004 def test_get_verify_mode_wrong_args(self):
1005 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001006 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001007 arguments.
1008 """
1009 context = Context(TLSv1_METHOD)
1010 self.assertRaises(TypeError, context.get_verify_mode, None)
1011
1012
1013 def test_get_verify_mode(self):
1014 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001015 :py:obj:`Context.get_verify_mode` returns the verify mode flags previously
1016 passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001017 """
1018 context = Context(TLSv1_METHOD)
1019 self.assertEquals(context.get_verify_mode(), 0)
1020 context.set_verify(
1021 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1022 self.assertEquals(
1023 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1024
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001025
1026 def test_load_tmp_dh_wrong_args(self):
1027 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001028 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
1029 number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001030 """
1031 context = Context(TLSv1_METHOD)
1032 self.assertRaises(TypeError, context.load_tmp_dh)
1033 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1034 self.assertRaises(TypeError, context.load_tmp_dh, object())
1035
1036
1037 def test_load_tmp_dh_missing_file(self):
1038 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001039 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the specified file
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001040 does not exist.
1041 """
1042 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001043 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001044
1045
1046 def test_load_tmp_dh(self):
1047 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001048 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001049 specified file.
1050 """
1051 context = Context(TLSv1_METHOD)
1052 dhfilename = self.mktemp()
1053 dhfile = open(dhfilename, "w")
1054 dhfile.write(dhparam)
1055 dhfile.close()
1056 context.load_tmp_dh(dhfilename)
1057 # XXX What should I assert here? -exarkun
1058
1059
1060 def test_set_cipher_list(self):
1061 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001062 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`str` naming the ciphers which
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001063 connections created with the context object will be able to choose from.
1064 """
1065 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001066 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001067 conn = Connection(context, None)
1068 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001069
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001070
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001071 def test_set_cipher_list_wrong_args(self):
1072 """
1073 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when passed
1074 zero arguments or more than one argument or when passed a non-byte
1075 string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
1076 passed an incorrect cipher list string.
1077 """
1078 context = Context(TLSv1_METHOD)
1079 self.assertRaises(TypeError, context.set_cipher_list)
1080 self.assertRaises(TypeError, context.set_cipher_list, object())
1081 self.assertRaises(TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object())
1082
1083 self.assertRaises(Error, context.set_cipher_list, b"imaginary-cipher")
1084
1085
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001086 def test_set_session_cache_mode_wrong_args(self):
1087 """
1088 L{Context.set_session_cache_mode} raises L{TypeError} if called with
1089 other than one integer argument.
1090 """
1091 context = Context(TLSv1_METHOD)
1092 self.assertRaises(TypeError, context.set_session_cache_mode)
1093 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1094
1095
1096 def test_get_session_cache_mode_wrong_args(self):
1097 """
1098 L{Context.get_session_cache_mode} raises L{TypeError} if called with any
1099 arguments.
1100 """
1101 context = Context(TLSv1_METHOD)
1102 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1103
1104
1105 def test_session_cache_mode(self):
1106 """
1107 L{Context.set_session_cache_mode} specifies how sessions are cached.
1108 The setting can be retrieved via L{Context.get_session_cache_mode}.
1109 """
1110 context = Context(TLSv1_METHOD)
1111 old = context.set_session_cache_mode(SESS_CACHE_OFF)
1112 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1113 self.assertEqual(SESS_CACHE_OFF, off)
1114 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1115
1116
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001117 def test_get_cert_store(self):
1118 """
1119 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store` instance.
1120 """
1121 context = Context(TLSv1_METHOD)
1122 store = context.get_cert_store()
1123 self.assertIsInstance(store, X509Store)
1124
1125
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001126
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001127class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1128 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001129 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
1130 :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001131 """
1132 def test_wrong_args(self):
1133 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001134 :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001135 with other than one argument.
1136 """
1137 context = Context(TLSv1_METHOD)
1138 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1139 self.assertRaises(
1140 TypeError, context.set_tlsext_servername_callback, 1, 2)
1141
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001142
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001143 def test_old_callback_forgotten(self):
1144 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001145 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001146 callback, the one it replaces is dereferenced.
1147 """
1148 def callback(connection):
1149 pass
1150
1151 def replacement(connection):
1152 pass
1153
1154 context = Context(TLSv1_METHOD)
1155 context.set_tlsext_servername_callback(callback)
1156
1157 tracker = ref(callback)
1158 del callback
1159
1160 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001161
1162 # One run of the garbage collector happens to work on CPython. PyPy
1163 # doesn't collect the underlying object until a second run for whatever
1164 # reason. That's fine, it still demonstrates our code has properly
1165 # dropped the reference.
1166 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001167 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001168
1169 callback = tracker()
1170 if callback is not None:
1171 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001172 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001173 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001174
1175
1176 def test_no_servername(self):
1177 """
1178 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001179 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
1180 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001181 """
1182 args = []
1183 def servername(conn):
1184 args.append((conn, conn.get_servername()))
1185 context = Context(TLSv1_METHOD)
1186 context.set_tlsext_servername_callback(servername)
1187
1188 # Lose our reference to it. The Context is responsible for keeping it
1189 # alive now.
1190 del servername
1191 collect()
1192
1193 # Necessary to actually accept the connection
1194 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1195 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1196
1197 # Do a little connection to trigger the logic
1198 server = Connection(context, None)
1199 server.set_accept_state()
1200
1201 client = Connection(Context(TLSv1_METHOD), None)
1202 client.set_connect_state()
1203
1204 self._interactInMemory(server, client)
1205
1206 self.assertEqual([(server, None)], args)
1207
1208
1209 def test_servername(self):
1210 """
1211 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +09001212 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
1213 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001214 """
1215 args = []
1216 def servername(conn):
1217 args.append((conn, conn.get_servername()))
1218 context = Context(TLSv1_METHOD)
1219 context.set_tlsext_servername_callback(servername)
1220
1221 # Necessary to actually accept the connection
1222 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1223 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1224
1225 # Do a little connection to trigger the logic
1226 server = Connection(context, None)
1227 server.set_accept_state()
1228
1229 client = Connection(Context(TLSv1_METHOD), None)
1230 client.set_connect_state()
1231 client.set_tlsext_host_name(b("foo1.example.com"))
1232
1233 self._interactInMemory(server, client)
1234
1235 self.assertEqual([(server, b("foo1.example.com"))], args)
1236
1237
1238
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001239class SessionTests(TestCase):
1240 """
1241 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1242 """
1243 def test_construction(self):
1244 """
1245 :py:class:`Session` can be constructed with no arguments, creating a new
1246 instance of that type.
1247 """
1248 new_session = Session()
1249 self.assertTrue(isinstance(new_session, Session))
1250
1251
1252 def test_construction_wrong_args(self):
1253 """
1254 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
1255 is raised.
1256 """
1257 self.assertRaises(TypeError, Session, 123)
1258 self.assertRaises(TypeError, Session, "hello")
1259 self.assertRaises(TypeError, Session, object())
1260
1261
1262
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001263class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05001264 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001265 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001266 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001267 # XXX get_peer_certificate -> None
1268 # XXX sock_shutdown
1269 # XXX master_key -> TypeError
1270 # XXX server_random -> TypeError
1271 # XXX state_string
1272 # XXX connect -> TypeError
1273 # XXX connect_ex -> TypeError
1274 # XXX set_connect_state -> TypeError
1275 # XXX set_accept_state -> TypeError
1276 # XXX renegotiate_pending
1277 # XXX do_handshake -> TypeError
1278 # XXX bio_read -> TypeError
1279 # XXX recv -> TypeError
1280 # XXX send -> TypeError
1281 # XXX bio_write -> TypeError
1282
Rick Deane15b1472009-07-09 15:53:42 -05001283 def test_type(self):
1284 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001285 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001286 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05001287 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001288 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05001289 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001290 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05001291
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001292
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001293 def test_get_context(self):
1294 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001295 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
1296 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001297 """
1298 context = Context(TLSv1_METHOD)
1299 connection = Connection(context, None)
1300 self.assertIdentical(connection.get_context(), context)
1301
1302
1303 def test_get_context_wrong_args(self):
1304 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001305 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001306 arguments.
1307 """
1308 connection = Connection(Context(TLSv1_METHOD), None)
1309 self.assertRaises(TypeError, connection.get_context, None)
1310
1311
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001312 def test_set_context_wrong_args(self):
1313 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001314 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
1315 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001316 than 1.
1317 """
1318 ctx = Context(TLSv1_METHOD)
1319 connection = Connection(ctx, None)
1320 self.assertRaises(TypeError, connection.set_context)
1321 self.assertRaises(TypeError, connection.set_context, object())
1322 self.assertRaises(TypeError, connection.set_context, "hello")
1323 self.assertRaises(TypeError, connection.set_context, 1)
1324 self.assertRaises(TypeError, connection.set_context, 1, 2)
1325 self.assertRaises(
1326 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
1327 self.assertIdentical(ctx, connection.get_context())
1328
1329
1330 def test_set_context(self):
1331 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001332 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001333 for the connection.
1334 """
1335 original = Context(SSLv23_METHOD)
1336 replacement = Context(TLSv1_METHOD)
1337 connection = Connection(original, None)
1338 connection.set_context(replacement)
1339 self.assertIdentical(replacement, connection.get_context())
1340 # Lose our references to the contexts, just in case the Connection isn't
1341 # properly managing its own contributions to their reference counts.
1342 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001343 collect()
1344
1345
1346 def test_set_tlsext_host_name_wrong_args(self):
1347 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001348 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001349 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09001350 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001351 """
1352 conn = Connection(Context(TLSv1_METHOD), None)
1353 self.assertRaises(TypeError, conn.set_tlsext_host_name)
1354 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
1355 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
1356 self.assertRaises(
1357 TypeError, conn.set_tlsext_host_name, b("with\0null"))
1358
1359 if version_info >= (3,):
1360 # On Python 3.x, don't accidentally implicitly convert from text.
1361 self.assertRaises(
1362 TypeError,
1363 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001364
1365
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001366 def test_get_servername_wrong_args(self):
1367 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001368 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001369 arguments.
1370 """
1371 connection = Connection(Context(TLSv1_METHOD), None)
1372 self.assertRaises(TypeError, connection.get_servername, object())
1373 self.assertRaises(TypeError, connection.get_servername, 1)
1374 self.assertRaises(TypeError, connection.get_servername, "hello")
1375
1376
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001377 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001378 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001379 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001380 immediate read.
1381 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001382 connection = Connection(Context(TLSv1_METHOD), None)
1383 self.assertEquals(connection.pending(), 0)
1384
1385
1386 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001387 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001388 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001389 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001390 connection = Connection(Context(TLSv1_METHOD), None)
1391 self.assertRaises(TypeError, connection.pending, None)
1392
1393
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001394 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001395 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001396 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001397 argument or with the wrong number of arguments.
1398 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001399 connection = Connection(Context(TLSv1_METHOD), socket())
1400 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001401 self.assertRaises(TypeError, connection.connect)
1402 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001403
1404
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001405 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001406 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001407 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001408 connect method raises it.
1409 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001410 client = socket()
1411 context = Context(TLSv1_METHOD)
1412 clientSSL = Connection(context, client)
1413 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04001414 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001415
1416
1417 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001418 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001419 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001420 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001421 port = socket()
1422 port.bind(('', 0))
1423 port.listen(3)
1424
1425 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001426 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
1427 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001428
1429
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001430 if platform == "darwin":
1431 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
1432 else:
1433 def test_connect_ex(self):
1434 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001435 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001436 errno instead of raising an exception.
1437 """
1438 port = socket()
1439 port.bind(('', 0))
1440 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001441
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001442 clientSSL = Connection(Context(TLSv1_METHOD), socket())
1443 clientSSL.setblocking(False)
1444 result = clientSSL.connect_ex(port.getsockname())
1445 expected = (EINPROGRESS, EWOULDBLOCK)
1446 self.assertTrue(
1447 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001448
1449
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001450 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001451 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001452 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001453 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001454 connection = Connection(Context(TLSv1_METHOD), socket())
1455 self.assertRaises(TypeError, connection.accept, None)
1456
1457
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001458 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001459 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001460 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
1461 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001462 connection originated from.
1463 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001464 ctx = Context(TLSv1_METHOD)
1465 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1466 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001467 port = socket()
1468 portSSL = Connection(ctx, port)
1469 portSSL.bind(('', 0))
1470 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001471
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001472 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001473
1474 # Calling portSSL.getsockname() here to get the server IP address sounds
1475 # great, but frequently fails on Windows.
1476 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001477
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001478 serverSSL, address = portSSL.accept()
1479
1480 self.assertTrue(isinstance(serverSSL, Connection))
1481 self.assertIdentical(serverSSL.get_context(), ctx)
1482 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001483
1484
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001485 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001486 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001487 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001488 number of arguments or with arguments other than integers.
1489 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001490 connection = Connection(Context(TLSv1_METHOD), None)
1491 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04001492 self.assertRaises(TypeError, connection.get_shutdown, None)
1493 self.assertRaises(TypeError, connection.set_shutdown)
1494 self.assertRaises(TypeError, connection.set_shutdown, None)
1495 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001496
1497
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001498 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001499 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001500 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001501 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001502 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001503 self.assertFalse(server.shutdown())
1504 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001505 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001506 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
1507 client.shutdown()
1508 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
1509 self.assertRaises(ZeroReturnError, server.recv, 1024)
1510 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001511
1512
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001513 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001514 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001515 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001516 process.
1517 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001518 connection = Connection(Context(TLSv1_METHOD), socket())
1519 connection.set_shutdown(RECEIVED_SHUTDOWN)
1520 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1521
1522
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001523 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001524 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001525 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
1526 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001527 with any arguments.
1528 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001529 conn = Connection(Context(TLSv1_METHOD), None)
1530 self.assertRaises(TypeError, conn.get_app_data, None)
1531 self.assertRaises(TypeError, conn.set_app_data)
1532 self.assertRaises(TypeError, conn.set_app_data, None, None)
1533
1534
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001535 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001536 """
1537 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001538 :py:obj:`Connection.set_app_data` and later retrieved with
1539 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001540 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001541 conn = Connection(Context(TLSv1_METHOD), None)
1542 app_data = object()
1543 conn.set_app_data(app_data)
1544 self.assertIdentical(conn.get_app_data(), app_data)
1545
1546
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001547 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001548 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001549 :py:obj:`Connection.makefile` is not implemented and calling that method raises
1550 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001551 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001552 conn = Connection(Context(TLSv1_METHOD), None)
1553 self.assertRaises(NotImplementedError, conn.makefile)
1554
1555
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001556 def test_get_peer_cert_chain_wrong_args(self):
1557 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001558 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001559 arguments.
1560 """
1561 conn = Connection(Context(TLSv1_METHOD), None)
1562 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
1563 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
1564 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
1565 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
1566
1567
1568 def test_get_peer_cert_chain(self):
1569 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001570 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001571 the connected server returned for the certification verification.
1572 """
1573 chain = _create_certificate_chain()
1574 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1575
1576 serverContext = Context(TLSv1_METHOD)
1577 serverContext.use_privatekey(skey)
1578 serverContext.use_certificate(scert)
1579 serverContext.add_extra_chain_cert(icert)
1580 serverContext.add_extra_chain_cert(cacert)
1581 server = Connection(serverContext, None)
1582 server.set_accept_state()
1583
1584 # Create the client
1585 clientContext = Context(TLSv1_METHOD)
1586 clientContext.set_verify(VERIFY_NONE, verify_cb)
1587 client = Connection(clientContext, None)
1588 client.set_connect_state()
1589
1590 self._interactInMemory(client, server)
1591
1592 chain = client.get_peer_cert_chain()
1593 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001594 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001595 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001596 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001597 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001598 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001599 "Authority Certificate", chain[2].get_subject().CN)
1600
1601
1602 def test_get_peer_cert_chain_none(self):
1603 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001604 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001605 certificate chain.
1606 """
1607 ctx = Context(TLSv1_METHOD)
1608 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1609 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1610 server = Connection(ctx, None)
1611 server.set_accept_state()
1612 client = Connection(Context(TLSv1_METHOD), None)
1613 client.set_connect_state()
1614 self._interactInMemory(client, server)
1615 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001616
1617
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001618 def test_get_session_wrong_args(self):
1619 """
1620 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
1621 with any arguments.
1622 """
1623 ctx = Context(TLSv1_METHOD)
1624 server = Connection(ctx, None)
1625 self.assertRaises(TypeError, server.get_session, 123)
1626 self.assertRaises(TypeError, server.get_session, "hello")
1627 self.assertRaises(TypeError, server.get_session, object())
1628
1629
1630 def test_get_session_unconnected(self):
1631 """
1632 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
1633 an object which has not been connected.
1634 """
1635 ctx = Context(TLSv1_METHOD)
1636 server = Connection(ctx, None)
1637 session = server.get_session()
1638 self.assertIdentical(None, session)
1639
1640
1641 def test_server_get_session(self):
1642 """
1643 On the server side of a connection, :py:obj:`Connection.get_session`
1644 returns a :py:class:`Session` instance representing the SSL session for
1645 that connection.
1646 """
1647 server, client = self._loopback()
1648 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001649 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001650
1651
1652 def test_client_get_session(self):
1653 """
1654 On the client side of a connection, :py:obj:`Connection.get_session`
1655 returns a :py:class:`Session` instance representing the SSL session for
1656 that connection.
1657 """
1658 server, client = self._loopback()
1659 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001660 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001661
1662
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05001663 def test_set_session_wrong_args(self):
1664 """
1665 If called with an object that is not an instance of :py:class:`Session`,
1666 or with other than one argument, :py:obj:`Connection.set_session` raises
1667 :py:obj:`TypeError`.
1668 """
1669 ctx = Context(TLSv1_METHOD)
1670 connection = Connection(ctx, None)
1671 self.assertRaises(TypeError, connection.set_session)
1672 self.assertRaises(TypeError, connection.set_session, 123)
1673 self.assertRaises(TypeError, connection.set_session, "hello")
1674 self.assertRaises(TypeError, connection.set_session, object())
1675 self.assertRaises(
1676 TypeError, connection.set_session, Session(), Session())
1677
1678
1679 def test_client_set_session(self):
1680 """
1681 :py:obj:`Connection.set_session`, when used prior to a connection being
1682 established, accepts a :py:class:`Session` instance and causes an
1683 attempt to re-use the session it represents when the SSL handshake is
1684 performed.
1685 """
1686 key = load_privatekey(FILETYPE_PEM, server_key_pem)
1687 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
1688 ctx = Context(TLSv1_METHOD)
1689 ctx.use_privatekey(key)
1690 ctx.use_certificate(cert)
1691 ctx.set_session_id("unity-test")
1692
1693 def makeServer(socket):
1694 server = Connection(ctx, socket)
1695 server.set_accept_state()
1696 return server
1697
1698 originalServer, originalClient = self._loopback(
1699 serverFactory=makeServer)
1700 originalSession = originalClient.get_session()
1701
1702 def makeClient(socket):
1703 client = self._loopbackClientFactory(socket)
1704 client.set_session(originalSession)
1705 return client
1706 resumedServer, resumedClient = self._loopback(
1707 serverFactory=makeServer,
1708 clientFactory=makeClient)
1709
1710 # This is a proxy: in general, we have no access to any unique
1711 # identifier for the session (new enough versions of OpenSSL expose a
1712 # hash which could be usable, but "new enough" is very, very new).
1713 # Instead, exploit the fact that the master key is re-used if the
1714 # session is re-used. As long as the master key for the two connections
1715 # is the same, the session was re-used!
1716 self.assertEqual(
1717 originalServer.master_key(), resumedServer.master_key())
1718
1719
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05001720 def test_set_session_wrong_method(self):
1721 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05001722 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
1723 instance associated with a context using a different SSL method than the
1724 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
1725 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05001726 """
1727 key = load_privatekey(FILETYPE_PEM, server_key_pem)
1728 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
1729 ctx = Context(TLSv1_METHOD)
1730 ctx.use_privatekey(key)
1731 ctx.use_certificate(cert)
1732 ctx.set_session_id("unity-test")
1733
1734 def makeServer(socket):
1735 server = Connection(ctx, socket)
1736 server.set_accept_state()
1737 return server
1738
1739 originalServer, originalClient = self._loopback(
1740 serverFactory=makeServer)
1741 originalSession = originalClient.get_session()
1742
1743 def makeClient(socket):
1744 # Intentionally use a different, incompatible method here.
1745 client = Connection(Context(SSLv3_METHOD), socket)
1746 client.set_connect_state()
1747 client.set_session(originalSession)
1748 return client
1749
1750 self.assertRaises(
1751 Error,
1752 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
1753
1754
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07001755 def test_wantWriteError(self):
1756 """
1757 :py:obj:`Connection` methods which generate output raise
1758 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
1759 fail indicating a should-write state.
1760 """
1761 client_socket, server_socket = socket_pair()
1762 # Fill up the client's send buffer so Connection won't be able to write
1763 # anything.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001764 msg = b"x" * 1024
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07001765 for i in range(1024):
1766 try:
1767 client_socket.send(msg)
1768 except error as e:
1769 if e.errno == EWOULDBLOCK:
1770 break
1771 raise
1772 else:
1773 self.fail(
1774 "Failed to fill socket buffer, cannot test BIO want write")
1775
1776 ctx = Context(TLSv1_METHOD)
1777 conn = Connection(ctx, client_socket)
1778 # Client's speak first, so make it an SSL client
1779 conn.set_connect_state()
1780 self.assertRaises(WantWriteError, conn.do_handshake)
1781
1782 # XXX want_read
1783
1784
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001785
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001786class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001787 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001788 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001789 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04001790 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001791 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001792 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001793 arguments.
1794 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001795 connection = Connection(Context(TLSv1_METHOD), None)
1796 self.assertRaises(TypeError, connection.get_cipher_list, None)
1797
1798
1799 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001800 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001801 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
1802 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001803 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001804 connection = Connection(Context(TLSv1_METHOD), None)
1805 ciphers = connection.get_cipher_list()
1806 self.assertTrue(isinstance(ciphers, list))
1807 for cipher in ciphers:
1808 self.assertTrue(isinstance(cipher, str))
1809
1810
1811
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001812class ConnectionSendTests(TestCase, _LoopbackMixin):
1813 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001814 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001815 """
1816 def test_wrong_args(self):
1817 """
1818 When called with arguments other than a single string,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001819 :py:obj:`Connection.send` raises :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001820 """
1821 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05001822 self.assertRaises(TypeError, connection.send)
1823 self.assertRaises(TypeError, connection.send, object())
1824 self.assertRaises(TypeError, connection.send, "foo", "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001825
1826
1827 def test_short_bytes(self):
1828 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001829 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001830 and returns the number of bytes sent.
1831 """
1832 server, client = self._loopback()
1833 count = server.send(b('xy'))
1834 self.assertEquals(count, 2)
1835 self.assertEquals(client.recv(2), b('xy'))
1836
1837 try:
1838 memoryview
1839 except NameError:
1840 "cannot test sending memoryview without memoryview"
1841 else:
1842 def test_short_memoryview(self):
1843 """
1844 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001845 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001846 bytes sent.
1847 """
1848 server, client = self._loopback()
1849 count = server.send(memoryview(b('xy')))
1850 self.assertEquals(count, 2)
1851 self.assertEquals(client.recv(2), b('xy'))
1852
1853
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05001854
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001855class ConnectionSendallTests(TestCase, _LoopbackMixin):
1856 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001857 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001858 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001859 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001860 """
1861 When called with arguments other than a single string,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001862 :py:obj:`Connection.sendall` raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001863 """
1864 connection = Connection(Context(TLSv1_METHOD), None)
1865 self.assertRaises(TypeError, connection.sendall)
1866 self.assertRaises(TypeError, connection.sendall, object())
1867 self.assertRaises(TypeError, connection.sendall, "foo", "bar")
1868
1869
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001870 def test_short(self):
1871 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001872 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001873 it.
1874 """
1875 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001876 server.sendall(b('x'))
1877 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001878
1879
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05001880 try:
1881 memoryview
1882 except NameError:
1883 "cannot test sending memoryview without memoryview"
1884 else:
1885 def test_short_memoryview(self):
1886 """
1887 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001888 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05001889 """
1890 server, client = self._loopback()
1891 server.sendall(memoryview(b('x')))
1892 self.assertEquals(client.recv(1), b('x'))
1893
1894
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001895 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001896 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001897 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001898 it even if this requires multiple calls of an underlying write function.
1899 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001900 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04001901 # Should be enough, underlying SSL_write should only do 16k at a time.
1902 # On Windows, after 32k of bytes the write will block (forever - because
1903 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04001904 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001905 server.sendall(message)
1906 accum = []
1907 received = 0
1908 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001909 data = client.recv(1024)
1910 accum.append(data)
1911 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04001912 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001913
1914
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001915 def test_closed(self):
1916 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001917 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001918 write error from the low level write call.
1919 """
1920 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04001921 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001922 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001923 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001924
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001925
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001926
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001927class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
1928 """
1929 Tests for SSL renegotiation APIs.
1930 """
1931 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001932 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001933 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001934 arguments.
1935 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001936 connection = Connection(Context(TLSv1_METHOD), None)
1937 self.assertRaises(TypeError, connection.renegotiate, None)
1938
1939
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001940 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001941 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001942 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001943 any arguments.
1944 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001945 connection = Connection(Context(TLSv1_METHOD), None)
1946 self.assertRaises(TypeError, connection.total_renegotiations, None)
1947
1948
1949 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001950 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001951 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001952 renegotiations have happened.
1953 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001954 connection = Connection(Context(TLSv1_METHOD), None)
1955 self.assertEquals(connection.total_renegotiations(), 0)
1956
1957
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001958# def test_renegotiate(self):
1959# """
1960# """
1961# server, client = self._loopback()
1962
1963# server.send("hello world")
1964# self.assertEquals(client.recv(len("hello world")), "hello world")
1965
1966# self.assertEquals(server.total_renegotiations(), 0)
1967# self.assertTrue(server.renegotiate())
1968
1969# server.setblocking(False)
1970# client.setblocking(False)
1971# while server.renegotiate_pending():
1972# client.do_handshake()
1973# server.do_handshake()
1974
1975# self.assertEquals(server.total_renegotiations(), 1)
1976
1977
1978
1979
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001980class ErrorTests(TestCase):
1981 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001982 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001983 """
1984 def test_type(self):
1985 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001986 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001987 """
1988 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05001989 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05001990
1991
1992
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001993class ConstantsTests(TestCase):
1994 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001995 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001996
1997 These are values defined by OpenSSL intended only to be used as flags to
1998 OpenSSL APIs. The only assertions it seems can be made about them is
1999 their values.
2000 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002001 # unittest.TestCase has no skip mechanism
2002 if OP_NO_QUERY_MTU is not None:
2003 def test_op_no_query_mtu(self):
2004 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002005 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002006 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002007 """
2008 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
2009 else:
2010 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002011
2012
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002013 if OP_COOKIE_EXCHANGE is not None:
2014 def test_op_cookie_exchange(self):
2015 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002016 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002017 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002018 """
2019 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
2020 else:
2021 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002022
2023
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002024 if OP_NO_TICKET is not None:
2025 def test_op_no_ticket(self):
2026 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002027 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002028 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002029 """
2030 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04002031 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002032 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05002033
2034
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002035 if OP_NO_COMPRESSION is not None:
2036 def test_op_no_compression(self):
2037 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002038 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
2039 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002040 """
2041 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
2042 else:
2043 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
2044
2045
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002046 def test_sess_cache_off(self):
2047 """
2048 The value of L{OpenSSL.SSL.SESS_CACHE_OFF} 0x0, the value of
2049 L{SSL_SESS_CACHE_OFF} defined by I{openssl/ssl.h}.
2050 """
2051 self.assertEqual(0x0, SESS_CACHE_OFF)
2052
2053
2054 def test_sess_cache_client(self):
2055 """
2056 The value of L{OpenSSL.SSL.SESS_CACHE_CLIENT} 0x1, the value of
2057 L{SSL_SESS_CACHE_CLIENT} defined by I{openssl/ssl.h}.
2058 """
2059 self.assertEqual(0x1, SESS_CACHE_CLIENT)
2060
2061
2062 def test_sess_cache_server(self):
2063 """
2064 The value of L{OpenSSL.SSL.SESS_CACHE_SERVER} 0x2, the value of
2065 L{SSL_SESS_CACHE_SERVER} defined by I{openssl/ssl.h}.
2066 """
2067 self.assertEqual(0x2, SESS_CACHE_SERVER)
2068
2069
2070 def test_sess_cache_both(self):
2071 """
2072 The value of L{OpenSSL.SSL.SESS_CACHE_BOTH} 0x3, the value of
2073 L{SSL_SESS_CACHE_BOTH} defined by I{openssl/ssl.h}.
2074 """
2075 self.assertEqual(0x3, SESS_CACHE_BOTH)
2076
2077
2078 def test_sess_cache_no_auto_clear(self):
2079 """
2080 The value of L{OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR} 0x80, the value of
2081 L{SSL_SESS_CACHE_NO_AUTO_CLEAR} defined by I{openssl/ssl.h}.
2082 """
2083 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
2084
2085
2086 def test_sess_cache_no_internal_lookup(self):
2087 """
2088 The value of L{OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP} 0x100, the
2089 value of L{SSL_SESS_CACHE_NO_INTERNAL_LOOKUP} defined by
2090 I{openssl/ssl.h}.
2091 """
2092 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
2093
2094
2095 def test_sess_cache_no_internal_store(self):
2096 """
2097 The value of L{OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE} 0x200, the
2098 value of L{SSL_SESS_CACHE_NO_INTERNAL_STORE} defined by
2099 I{openssl/ssl.h}.
2100 """
2101 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
2102
2103
2104 def test_sess_cache_no_internal(self):
2105 """
2106 The value of L{OpenSSL.SSL.SESS_CACHE_NO_INTERNAL} 0x300, the value of
2107 L{SSL_SESS_CACHE_NO_INTERNAL} defined by I{openssl/ssl.h}.
2108 """
2109 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
2110
2111
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04002112
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002113class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05002114 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002115 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05002116 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002117 def _server(self, sock):
2118 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002119 Create a new server-side SSL :py:obj:`Connection` object wrapped around
2120 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002121 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002122 # Create the server side Connection. This is mostly setup boilerplate
2123 # - use TLSv1, use a particular certificate, etc.
2124 server_ctx = Context(TLSv1_METHOD)
2125 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2126 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2127 server_store = server_ctx.get_cert_store()
2128 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2129 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2130 server_ctx.check_privatekey()
2131 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002132 # Here the Connection is actually created. If None is passed as the 2nd
2133 # parameter, it indicates a memory BIO should be created.
2134 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002135 server_conn.set_accept_state()
2136 return server_conn
2137
2138
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002139 def _client(self, sock):
2140 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002141 Create a new client-side SSL :py:obj:`Connection` object wrapped around
2142 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002143 """
2144 # Now create the client side Connection. Similar boilerplate to the
2145 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002146 client_ctx = Context(TLSv1_METHOD)
2147 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2148 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2149 client_store = client_ctx.get_cert_store()
2150 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
2151 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
2152 client_ctx.check_privatekey()
2153 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002154 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002155 client_conn.set_connect_state()
2156 return client_conn
2157
2158
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002159 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002160 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002161 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002162 reading from the output of each and writing those bytes to the input of
2163 the other and in this way establish a connection and exchange
2164 application-level bytes with each other.
2165 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002166 server_conn = self._server(None)
2167 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002168
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002169 # There should be no key or nonces yet.
2170 self.assertIdentical(server_conn.master_key(), None)
2171 self.assertIdentical(server_conn.client_random(), None)
2172 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002173
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002174 # First, the handshake needs to happen. We'll deliver bytes back and
2175 # forth between the client and server until neither of them feels like
2176 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002177 self.assertIdentical(
2178 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002179
2180 # Now that the handshake is done, there should be a key and nonces.
2181 self.assertNotIdentical(server_conn.master_key(), None)
2182 self.assertNotIdentical(server_conn.client_random(), None)
2183 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04002184 self.assertEquals(server_conn.client_random(), client_conn.client_random())
2185 self.assertEquals(server_conn.server_random(), client_conn.server_random())
2186 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
2187 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002188
2189 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002190 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05002191
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002192 server_conn.write(important_message)
2193 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002194 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002195 (client_conn, important_message))
2196
2197 client_conn.write(important_message[::-1])
2198 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002199 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002200 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05002201
2202
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002203 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05002204 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002205 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002206
2207 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09002208 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002209 this test fails, there must be a problem outside the memory BIO
2210 code, as no memory BIO is involved here). Even though this isn't a
2211 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05002212 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04002213 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05002214
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002215 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05002216 client_conn.send(important_message)
2217 msg = server_conn.recv(1024)
2218 self.assertEqual(msg, important_message)
2219
2220 # Again in the other direction, just for fun.
2221 important_message = important_message[::-1]
2222 server_conn.send(important_message)
2223 msg = client_conn.recv(1024)
2224 self.assertEqual(msg, important_message)
2225
2226
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04002227 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05002228 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002229 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
2230 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05002231 """
2232 context = Context(SSLv3_METHOD)
2233 client = socket()
2234 clientSSL = Connection(context, client)
2235 self.assertRaises( TypeError, clientSSL.bio_read, 100)
2236 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04002237 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002238
2239
2240 def test_outgoingOverflow(self):
2241 """
2242 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002243 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002244 returned and that many bytes from the beginning of the input can be
2245 read from the other end of the connection.
2246 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002247 server = self._server(None)
2248 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002249
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002250 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002251
2252 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002253 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002254 # Sanity check. We're trying to test what happens when the entire
2255 # input can't be sent. If the entire input was sent, this test is
2256 # meaningless.
2257 self.assertTrue(sent < size)
2258
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002259 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002260 self.assertIdentical(receiver, server)
2261
2262 # We can rely on all of these bytes being received at once because
2263 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
2264 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002265
2266
2267 def test_shutdown(self):
2268 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002269 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
2270 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002271 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002272 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002273 server.bio_shutdown()
2274 e = self.assertRaises(Error, server.recv, 1024)
2275 # We don't want WantReadError or ZeroReturnError or anything - it's a
2276 # handshake failure.
2277 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002278
2279
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002280 def test_unexpectedEndOfFile(self):
2281 """
2282 If the connection is lost before an orderly SSL shutdown occurs,
2283 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
2284 "Unexpected EOF".
2285 """
2286 server_conn, client_conn = self._loopback()
2287 client_conn.sock_shutdown(SHUT_RDWR)
2288 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
2289 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
2290
2291
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002292 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002293 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002294 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 -04002295
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002296 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002297 before the client and server are connected to each other. This
2298 function should specify a list of CAs for the server to send to the
2299 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09002300 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002301 times.
2302 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002303 server = self._server(None)
2304 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002305 self.assertEqual(client.get_client_ca_list(), [])
2306 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002307 ctx = server.get_context()
2308 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002309 self.assertEqual(client.get_client_ca_list(), [])
2310 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002311 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002312 self.assertEqual(client.get_client_ca_list(), expected)
2313 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002314
2315
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002316 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002317 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002318 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002319 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002320 """
2321 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002322 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
2323 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
2324 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002325
2326
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002327 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002328 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002329 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002330 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09002331 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002332 after the connection is set up.
2333 """
2334 def no_ca(ctx):
2335 ctx.set_client_ca_list([])
2336 return []
2337 self._check_client_ca_list(no_ca)
2338
2339
2340 def test_set_one_ca_list(self):
2341 """
2342 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002343 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002344 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002345 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002346 X509Name after the connection is set up.
2347 """
2348 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2349 cadesc = cacert.get_subject()
2350 def single_ca(ctx):
2351 ctx.set_client_ca_list([cadesc])
2352 return [cadesc]
2353 self._check_client_ca_list(single_ca)
2354
2355
2356 def test_set_multiple_ca_list(self):
2357 """
2358 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002359 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002360 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002361 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002362 X509Names after the connection is set up.
2363 """
2364 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2365 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2366
2367 sedesc = secert.get_subject()
2368 cldesc = clcert.get_subject()
2369
2370 def multiple_ca(ctx):
2371 L = [sedesc, cldesc]
2372 ctx.set_client_ca_list(L)
2373 return L
2374 self._check_client_ca_list(multiple_ca)
2375
2376
2377 def test_reset_ca_list(self):
2378 """
2379 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09002380 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002381 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002382 """
2383 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2384 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2385 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2386
2387 cadesc = cacert.get_subject()
2388 sedesc = secert.get_subject()
2389 cldesc = clcert.get_subject()
2390
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002391 def changed_ca(ctx):
2392 ctx.set_client_ca_list([sedesc, cldesc])
2393 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002394 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002395 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002396
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002397
2398 def test_mutated_ca_list(self):
2399 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002400 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002401 afterwards, this does not affect the list of CA names sent to the
2402 client.
2403 """
2404 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2405 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2406
2407 cadesc = cacert.get_subject()
2408 sedesc = secert.get_subject()
2409
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002410 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002411 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002412 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002413 L.append(sedesc)
2414 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002415 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002416
2417
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002418 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002419 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002420 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002421 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002422 """
2423 ctx = Context(TLSv1_METHOD)
2424 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002425 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002426 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002427 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002428
2429
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002430 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002431 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002432 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09002433 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002434 """
2435 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2436 cadesc = cacert.get_subject()
2437 def single_ca(ctx):
2438 ctx.add_client_ca(cacert)
2439 return [cadesc]
2440 self._check_client_ca_list(single_ca)
2441
2442
2443 def test_multiple_add_client_ca(self):
2444 """
2445 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09002446 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002447 """
2448 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2449 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2450
2451 cadesc = cacert.get_subject()
2452 sedesc = secert.get_subject()
2453
2454 def multiple_ca(ctx):
2455 ctx.add_client_ca(cacert)
2456 ctx.add_client_ca(secert)
2457 return [cadesc, sedesc]
2458 self._check_client_ca_list(multiple_ca)
2459
2460
2461 def test_set_and_add_client_ca(self):
2462 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002463 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
2464 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002465 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002466 """
2467 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2468 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2469 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2470
2471 cadesc = cacert.get_subject()
2472 sedesc = secert.get_subject()
2473 cldesc = clcert.get_subject()
2474
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002475 def mixed_set_add_ca(ctx):
2476 ctx.set_client_ca_list([cadesc, sedesc])
2477 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002478 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002479 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002480
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002481
2482 def test_set_after_add_client_ca(self):
2483 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002484 A call to :py:obj:`Context.set_client_ca_list` after a call to
2485 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002486 call with the names specified by the latter cal.
2487 """
2488 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2489 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2490 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2491
2492 cadesc = cacert.get_subject()
2493 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002494
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002495 def set_replaces_add_ca(ctx):
2496 ctx.add_client_ca(clcert)
2497 ctx.set_client_ca_list([cadesc])
2498 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002499 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002500 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002501
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002502
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002503
2504class ConnectionBIOTests(TestCase):
2505 """
2506 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
2507 """
2508 def test_wantReadError(self):
2509 """
2510 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
2511 if there are no bytes available to be read from the BIO.
2512 """
2513 ctx = Context(TLSv1_METHOD)
2514 conn = Connection(ctx, None)
2515 self.assertRaises(WantReadError, conn.bio_read, 1024)
2516
2517
2518
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04002519class InfoConstantTests(TestCase):
2520 """
2521 Tests for assorted constants exposed for use in info callbacks.
2522 """
2523 def test_integers(self):
2524 """
2525 All of the info constants are integers.
2526
2527 This is a very weak test. It would be nice to have one that actually
2528 verifies that as certain info events happen, the value passed to the
2529 info callback matches up with the constant exposed by OpenSSL.SSL.
2530 """
2531 for const in [
2532 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
2533 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
2534 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
2535 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
2536 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
2537 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
2538
2539 self.assertTrue(isinstance(const, int))
2540
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02002541
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002542if __name__ == '__main__':
2543 main()