blob: 881d4096b4348749ad99fdd02cd74a5d75ea506d [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 Calderonec4cb6582011-05-26 18:47:00 -04008from gc import collect
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 Calderone9e4eeae2010-08-22 21:32:52 -040042from OpenSSL.test.util import TestCase, bytes, 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()
439 with open(pem_filename, "w") as pem_file:
440 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 Calderone8a1bea52013-03-05 07:57:57 -0800638 return ""
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.
783 for name in ['c7adac82.0', 'c3705638.0']:
784 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()
833 clientSSL.send('GET / HTTP/1.0\r\n\r\n')
834 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)
943 clientContext.load_verify_locations('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)
981 clientContext.load_verify_locations('ca.pem')
982
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)
1043 self.assertRaises(Error, context.load_tmp_dh, "hello")
1044
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)
1066 context.set_cipher_list("hello world:EXP-RC4-MD5")
1067 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
1142 def test_old_callback_forgotten(self):
1143 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001144 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001145 callback, the one it replaces is dereferenced.
1146 """
1147 def callback(connection):
1148 pass
1149
1150 def replacement(connection):
1151 pass
1152
1153 context = Context(TLSv1_METHOD)
1154 context.set_tlsext_servername_callback(callback)
1155
1156 tracker = ref(callback)
1157 del callback
1158
1159 context.set_tlsext_servername_callback(replacement)
1160 collect()
1161 self.assertIdentical(None, tracker())
1162
1163
1164 def test_no_servername(self):
1165 """
1166 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001167 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
1168 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001169 """
1170 args = []
1171 def servername(conn):
1172 args.append((conn, conn.get_servername()))
1173 context = Context(TLSv1_METHOD)
1174 context.set_tlsext_servername_callback(servername)
1175
1176 # Lose our reference to it. The Context is responsible for keeping it
1177 # alive now.
1178 del servername
1179 collect()
1180
1181 # Necessary to actually accept the connection
1182 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1183 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1184
1185 # Do a little connection to trigger the logic
1186 server = Connection(context, None)
1187 server.set_accept_state()
1188
1189 client = Connection(Context(TLSv1_METHOD), None)
1190 client.set_connect_state()
1191
1192 self._interactInMemory(server, client)
1193
1194 self.assertEqual([(server, None)], args)
1195
1196
1197 def test_servername(self):
1198 """
1199 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +09001200 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
1201 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001202 """
1203 args = []
1204 def servername(conn):
1205 args.append((conn, conn.get_servername()))
1206 context = Context(TLSv1_METHOD)
1207 context.set_tlsext_servername_callback(servername)
1208
1209 # Necessary to actually accept the connection
1210 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1211 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1212
1213 # Do a little connection to trigger the logic
1214 server = Connection(context, None)
1215 server.set_accept_state()
1216
1217 client = Connection(Context(TLSv1_METHOD), None)
1218 client.set_connect_state()
1219 client.set_tlsext_host_name(b("foo1.example.com"))
1220
1221 self._interactInMemory(server, client)
1222
1223 self.assertEqual([(server, b("foo1.example.com"))], args)
1224
1225
1226
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001227class SessionTests(TestCase):
1228 """
1229 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1230 """
1231 def test_construction(self):
1232 """
1233 :py:class:`Session` can be constructed with no arguments, creating a new
1234 instance of that type.
1235 """
1236 new_session = Session()
1237 self.assertTrue(isinstance(new_session, Session))
1238
1239
1240 def test_construction_wrong_args(self):
1241 """
1242 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
1243 is raised.
1244 """
1245 self.assertRaises(TypeError, Session, 123)
1246 self.assertRaises(TypeError, Session, "hello")
1247 self.assertRaises(TypeError, Session, object())
1248
1249
1250
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001251class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05001252 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001253 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001254 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001255 # XXX get_peer_certificate -> None
1256 # XXX sock_shutdown
1257 # XXX master_key -> TypeError
1258 # XXX server_random -> TypeError
1259 # XXX state_string
1260 # XXX connect -> TypeError
1261 # XXX connect_ex -> TypeError
1262 # XXX set_connect_state -> TypeError
1263 # XXX set_accept_state -> TypeError
1264 # XXX renegotiate_pending
1265 # XXX do_handshake -> TypeError
1266 # XXX bio_read -> TypeError
1267 # XXX recv -> TypeError
1268 # XXX send -> TypeError
1269 # XXX bio_write -> TypeError
1270
Rick Deane15b1472009-07-09 15:53:42 -05001271 def test_type(self):
1272 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001273 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001274 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05001275 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001276 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05001277 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001278 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05001279
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001280
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001281 def test_get_context(self):
1282 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001283 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
1284 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001285 """
1286 context = Context(TLSv1_METHOD)
1287 connection = Connection(context, None)
1288 self.assertIdentical(connection.get_context(), context)
1289
1290
1291 def test_get_context_wrong_args(self):
1292 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001293 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001294 arguments.
1295 """
1296 connection = Connection(Context(TLSv1_METHOD), None)
1297 self.assertRaises(TypeError, connection.get_context, None)
1298
1299
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001300 def test_set_context_wrong_args(self):
1301 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001302 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
1303 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001304 than 1.
1305 """
1306 ctx = Context(TLSv1_METHOD)
1307 connection = Connection(ctx, None)
1308 self.assertRaises(TypeError, connection.set_context)
1309 self.assertRaises(TypeError, connection.set_context, object())
1310 self.assertRaises(TypeError, connection.set_context, "hello")
1311 self.assertRaises(TypeError, connection.set_context, 1)
1312 self.assertRaises(TypeError, connection.set_context, 1, 2)
1313 self.assertRaises(
1314 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
1315 self.assertIdentical(ctx, connection.get_context())
1316
1317
1318 def test_set_context(self):
1319 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001320 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001321 for the connection.
1322 """
1323 original = Context(SSLv23_METHOD)
1324 replacement = Context(TLSv1_METHOD)
1325 connection = Connection(original, None)
1326 connection.set_context(replacement)
1327 self.assertIdentical(replacement, connection.get_context())
1328 # Lose our references to the contexts, just in case the Connection isn't
1329 # properly managing its own contributions to their reference counts.
1330 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001331 collect()
1332
1333
1334 def test_set_tlsext_host_name_wrong_args(self):
1335 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001336 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001337 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09001338 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001339 """
1340 conn = Connection(Context(TLSv1_METHOD), None)
1341 self.assertRaises(TypeError, conn.set_tlsext_host_name)
1342 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
1343 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
1344 self.assertRaises(
1345 TypeError, conn.set_tlsext_host_name, b("with\0null"))
1346
1347 if version_info >= (3,):
1348 # On Python 3.x, don't accidentally implicitly convert from text.
1349 self.assertRaises(
1350 TypeError,
1351 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001352
1353
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001354 def test_get_servername_wrong_args(self):
1355 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001356 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001357 arguments.
1358 """
1359 connection = Connection(Context(TLSv1_METHOD), None)
1360 self.assertRaises(TypeError, connection.get_servername, object())
1361 self.assertRaises(TypeError, connection.get_servername, 1)
1362 self.assertRaises(TypeError, connection.get_servername, "hello")
1363
1364
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001365 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001366 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001367 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001368 immediate read.
1369 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001370 connection = Connection(Context(TLSv1_METHOD), None)
1371 self.assertEquals(connection.pending(), 0)
1372
1373
1374 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001375 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001376 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001377 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001378 connection = Connection(Context(TLSv1_METHOD), None)
1379 self.assertRaises(TypeError, connection.pending, None)
1380
1381
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001382 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001383 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001384 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001385 argument or with the wrong number of arguments.
1386 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001387 connection = Connection(Context(TLSv1_METHOD), socket())
1388 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001389 self.assertRaises(TypeError, connection.connect)
1390 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001391
1392
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001393 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001394 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001395 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001396 connect method raises it.
1397 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001398 client = socket()
1399 context = Context(TLSv1_METHOD)
1400 clientSSL = Connection(context, client)
1401 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04001402 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001403
1404
1405 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001406 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001407 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001408 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001409 port = socket()
1410 port.bind(('', 0))
1411 port.listen(3)
1412
1413 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001414 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
1415 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001416
1417
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001418 if platform == "darwin":
1419 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
1420 else:
1421 def test_connect_ex(self):
1422 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001423 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001424 errno instead of raising an exception.
1425 """
1426 port = socket()
1427 port.bind(('', 0))
1428 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001429
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001430 clientSSL = Connection(Context(TLSv1_METHOD), socket())
1431 clientSSL.setblocking(False)
1432 result = clientSSL.connect_ex(port.getsockname())
1433 expected = (EINPROGRESS, EWOULDBLOCK)
1434 self.assertTrue(
1435 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001436
1437
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001438 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001439 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001440 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001441 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001442 connection = Connection(Context(TLSv1_METHOD), socket())
1443 self.assertRaises(TypeError, connection.accept, None)
1444
1445
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001446 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001447 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001448 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
1449 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001450 connection originated from.
1451 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001452 ctx = Context(TLSv1_METHOD)
1453 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1454 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001455 port = socket()
1456 portSSL = Connection(ctx, port)
1457 portSSL.bind(('', 0))
1458 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001459
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001460 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001461
1462 # Calling portSSL.getsockname() here to get the server IP address sounds
1463 # great, but frequently fails on Windows.
1464 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001465
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001466 serverSSL, address = portSSL.accept()
1467
1468 self.assertTrue(isinstance(serverSSL, Connection))
1469 self.assertIdentical(serverSSL.get_context(), ctx)
1470 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001471
1472
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001473 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001474 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001475 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001476 number of arguments or with arguments other than integers.
1477 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001478 connection = Connection(Context(TLSv1_METHOD), None)
1479 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04001480 self.assertRaises(TypeError, connection.get_shutdown, None)
1481 self.assertRaises(TypeError, connection.set_shutdown)
1482 self.assertRaises(TypeError, connection.set_shutdown, None)
1483 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001484
1485
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001486 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001487 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001488 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001489 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001490 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001491 self.assertFalse(server.shutdown())
1492 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001493 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001494 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
1495 client.shutdown()
1496 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
1497 self.assertRaises(ZeroReturnError, server.recv, 1024)
1498 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001499
1500
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001501 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001502 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001503 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001504 process.
1505 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001506 connection = Connection(Context(TLSv1_METHOD), socket())
1507 connection.set_shutdown(RECEIVED_SHUTDOWN)
1508 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1509
1510
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001511 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001512 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001513 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
1514 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001515 with any arguments.
1516 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001517 conn = Connection(Context(TLSv1_METHOD), None)
1518 self.assertRaises(TypeError, conn.get_app_data, None)
1519 self.assertRaises(TypeError, conn.set_app_data)
1520 self.assertRaises(TypeError, conn.set_app_data, None, None)
1521
1522
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001523 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001524 """
1525 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001526 :py:obj:`Connection.set_app_data` and later retrieved with
1527 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001528 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001529 conn = Connection(Context(TLSv1_METHOD), None)
1530 app_data = object()
1531 conn.set_app_data(app_data)
1532 self.assertIdentical(conn.get_app_data(), app_data)
1533
1534
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001535 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001536 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001537 :py:obj:`Connection.makefile` is not implemented and calling that method raises
1538 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001539 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001540 conn = Connection(Context(TLSv1_METHOD), None)
1541 self.assertRaises(NotImplementedError, conn.makefile)
1542
1543
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001544 def test_get_peer_cert_chain_wrong_args(self):
1545 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001546 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001547 arguments.
1548 """
1549 conn = Connection(Context(TLSv1_METHOD), None)
1550 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
1551 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
1552 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
1553 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
1554
1555
1556 def test_get_peer_cert_chain(self):
1557 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001558 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001559 the connected server returned for the certification verification.
1560 """
1561 chain = _create_certificate_chain()
1562 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1563
1564 serverContext = Context(TLSv1_METHOD)
1565 serverContext.use_privatekey(skey)
1566 serverContext.use_certificate(scert)
1567 serverContext.add_extra_chain_cert(icert)
1568 serverContext.add_extra_chain_cert(cacert)
1569 server = Connection(serverContext, None)
1570 server.set_accept_state()
1571
1572 # Create the client
1573 clientContext = Context(TLSv1_METHOD)
1574 clientContext.set_verify(VERIFY_NONE, verify_cb)
1575 client = Connection(clientContext, None)
1576 client.set_connect_state()
1577
1578 self._interactInMemory(client, server)
1579
1580 chain = client.get_peer_cert_chain()
1581 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001582 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001583 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001584 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001585 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001586 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001587 "Authority Certificate", chain[2].get_subject().CN)
1588
1589
1590 def test_get_peer_cert_chain_none(self):
1591 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001592 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001593 certificate chain.
1594 """
1595 ctx = Context(TLSv1_METHOD)
1596 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1597 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1598 server = Connection(ctx, None)
1599 server.set_accept_state()
1600 client = Connection(Context(TLSv1_METHOD), None)
1601 client.set_connect_state()
1602 self._interactInMemory(client, server)
1603 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001604
1605
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001606 def test_get_session_wrong_args(self):
1607 """
1608 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
1609 with any arguments.
1610 """
1611 ctx = Context(TLSv1_METHOD)
1612 server = Connection(ctx, None)
1613 self.assertRaises(TypeError, server.get_session, 123)
1614 self.assertRaises(TypeError, server.get_session, "hello")
1615 self.assertRaises(TypeError, server.get_session, object())
1616
1617
1618 def test_get_session_unconnected(self):
1619 """
1620 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
1621 an object which has not been connected.
1622 """
1623 ctx = Context(TLSv1_METHOD)
1624 server = Connection(ctx, None)
1625 session = server.get_session()
1626 self.assertIdentical(None, session)
1627
1628
1629 def test_server_get_session(self):
1630 """
1631 On the server side of a connection, :py:obj:`Connection.get_session`
1632 returns a :py:class:`Session` instance representing the SSL session for
1633 that connection.
1634 """
1635 server, client = self._loopback()
1636 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001637 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001638
1639
1640 def test_client_get_session(self):
1641 """
1642 On the client side of a connection, :py:obj:`Connection.get_session`
1643 returns a :py:class:`Session` instance representing the SSL session for
1644 that connection.
1645 """
1646 server, client = self._loopback()
1647 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001648 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001649
1650
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05001651 def test_set_session_wrong_args(self):
1652 """
1653 If called with an object that is not an instance of :py:class:`Session`,
1654 or with other than one argument, :py:obj:`Connection.set_session` raises
1655 :py:obj:`TypeError`.
1656 """
1657 ctx = Context(TLSv1_METHOD)
1658 connection = Connection(ctx, None)
1659 self.assertRaises(TypeError, connection.set_session)
1660 self.assertRaises(TypeError, connection.set_session, 123)
1661 self.assertRaises(TypeError, connection.set_session, "hello")
1662 self.assertRaises(TypeError, connection.set_session, object())
1663 self.assertRaises(
1664 TypeError, connection.set_session, Session(), Session())
1665
1666
1667 def test_client_set_session(self):
1668 """
1669 :py:obj:`Connection.set_session`, when used prior to a connection being
1670 established, accepts a :py:class:`Session` instance and causes an
1671 attempt to re-use the session it represents when the SSL handshake is
1672 performed.
1673 """
1674 key = load_privatekey(FILETYPE_PEM, server_key_pem)
1675 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
1676 ctx = Context(TLSv1_METHOD)
1677 ctx.use_privatekey(key)
1678 ctx.use_certificate(cert)
1679 ctx.set_session_id("unity-test")
1680
1681 def makeServer(socket):
1682 server = Connection(ctx, socket)
1683 server.set_accept_state()
1684 return server
1685
1686 originalServer, originalClient = self._loopback(
1687 serverFactory=makeServer)
1688 originalSession = originalClient.get_session()
1689
1690 def makeClient(socket):
1691 client = self._loopbackClientFactory(socket)
1692 client.set_session(originalSession)
1693 return client
1694 resumedServer, resumedClient = self._loopback(
1695 serverFactory=makeServer,
1696 clientFactory=makeClient)
1697
1698 # This is a proxy: in general, we have no access to any unique
1699 # identifier for the session (new enough versions of OpenSSL expose a
1700 # hash which could be usable, but "new enough" is very, very new).
1701 # Instead, exploit the fact that the master key is re-used if the
1702 # session is re-used. As long as the master key for the two connections
1703 # is the same, the session was re-used!
1704 self.assertEqual(
1705 originalServer.master_key(), resumedServer.master_key())
1706
1707
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05001708 def test_set_session_wrong_method(self):
1709 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05001710 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
1711 instance associated with a context using a different SSL method than the
1712 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
1713 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05001714 """
1715 key = load_privatekey(FILETYPE_PEM, server_key_pem)
1716 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
1717 ctx = Context(TLSv1_METHOD)
1718 ctx.use_privatekey(key)
1719 ctx.use_certificate(cert)
1720 ctx.set_session_id("unity-test")
1721
1722 def makeServer(socket):
1723 server = Connection(ctx, socket)
1724 server.set_accept_state()
1725 return server
1726
1727 originalServer, originalClient = self._loopback(
1728 serverFactory=makeServer)
1729 originalSession = originalClient.get_session()
1730
1731 def makeClient(socket):
1732 # Intentionally use a different, incompatible method here.
1733 client = Connection(Context(SSLv3_METHOD), socket)
1734 client.set_connect_state()
1735 client.set_session(originalSession)
1736 return client
1737
1738 self.assertRaises(
1739 Error,
1740 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
1741
1742
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07001743 def test_wantWriteError(self):
1744 """
1745 :py:obj:`Connection` methods which generate output raise
1746 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
1747 fail indicating a should-write state.
1748 """
1749 client_socket, server_socket = socket_pair()
1750 # Fill up the client's send buffer so Connection won't be able to write
1751 # anything.
1752 msg = 'x' * 1024
1753 for i in range(1024):
1754 try:
1755 client_socket.send(msg)
1756 except error as e:
1757 if e.errno == EWOULDBLOCK:
1758 break
1759 raise
1760 else:
1761 self.fail(
1762 "Failed to fill socket buffer, cannot test BIO want write")
1763
1764 ctx = Context(TLSv1_METHOD)
1765 conn = Connection(ctx, client_socket)
1766 # Client's speak first, so make it an SSL client
1767 conn.set_connect_state()
1768 self.assertRaises(WantWriteError, conn.do_handshake)
1769
1770 # XXX want_read
1771
1772
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001773
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001774class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001775 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001776 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001777 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04001778 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001779 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001780 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001781 arguments.
1782 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001783 connection = Connection(Context(TLSv1_METHOD), None)
1784 self.assertRaises(TypeError, connection.get_cipher_list, None)
1785
1786
1787 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001788 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001789 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of :py:obj:`str` giving the
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001790 names of the ciphers which might be used.
1791 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001792 connection = Connection(Context(TLSv1_METHOD), None)
1793 ciphers = connection.get_cipher_list()
1794 self.assertTrue(isinstance(ciphers, list))
1795 for cipher in ciphers:
1796 self.assertTrue(isinstance(cipher, str))
1797
1798
1799
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001800class ConnectionSendTests(TestCase, _LoopbackMixin):
1801 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001802 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001803 """
1804 def test_wrong_args(self):
1805 """
1806 When called with arguments other than a single string,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001807 :py:obj:`Connection.send` raises :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001808 """
1809 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05001810 self.assertRaises(TypeError, connection.send)
1811 self.assertRaises(TypeError, connection.send, object())
1812 self.assertRaises(TypeError, connection.send, "foo", "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001813
1814
1815 def test_short_bytes(self):
1816 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001817 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001818 and returns the number of bytes sent.
1819 """
1820 server, client = self._loopback()
1821 count = server.send(b('xy'))
1822 self.assertEquals(count, 2)
1823 self.assertEquals(client.recv(2), b('xy'))
1824
1825 try:
1826 memoryview
1827 except NameError:
1828 "cannot test sending memoryview without memoryview"
1829 else:
1830 def test_short_memoryview(self):
1831 """
1832 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001833 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001834 bytes sent.
1835 """
1836 server, client = self._loopback()
1837 count = server.send(memoryview(b('xy')))
1838 self.assertEquals(count, 2)
1839 self.assertEquals(client.recv(2), b('xy'))
1840
1841
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05001842
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001843class ConnectionSendallTests(TestCase, _LoopbackMixin):
1844 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001845 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001846 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001847 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001848 """
1849 When called with arguments other than a single string,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001850 :py:obj:`Connection.sendall` raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001851 """
1852 connection = Connection(Context(TLSv1_METHOD), None)
1853 self.assertRaises(TypeError, connection.sendall)
1854 self.assertRaises(TypeError, connection.sendall, object())
1855 self.assertRaises(TypeError, connection.sendall, "foo", "bar")
1856
1857
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001858 def test_short(self):
1859 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001860 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001861 it.
1862 """
1863 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001864 server.sendall(b('x'))
1865 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001866
1867
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05001868 try:
1869 memoryview
1870 except NameError:
1871 "cannot test sending memoryview without memoryview"
1872 else:
1873 def test_short_memoryview(self):
1874 """
1875 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001876 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05001877 """
1878 server, client = self._loopback()
1879 server.sendall(memoryview(b('x')))
1880 self.assertEquals(client.recv(1), b('x'))
1881
1882
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001883 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001884 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001885 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001886 it even if this requires multiple calls of an underlying write function.
1887 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001888 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04001889 # Should be enough, underlying SSL_write should only do 16k at a time.
1890 # On Windows, after 32k of bytes the write will block (forever - because
1891 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04001892 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001893 server.sendall(message)
1894 accum = []
1895 received = 0
1896 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001897 data = client.recv(1024)
1898 accum.append(data)
1899 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04001900 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001901
1902
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001903 def test_closed(self):
1904 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001905 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001906 write error from the low level write call.
1907 """
1908 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04001909 server.sock_shutdown(2)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001910 exc = self.assertRaises(SysCallError, server.sendall, "hello, world")
1911 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001912
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001913
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001914
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001915class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
1916 """
1917 Tests for SSL renegotiation APIs.
1918 """
1919 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001920 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001921 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001922 arguments.
1923 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001924 connection = Connection(Context(TLSv1_METHOD), None)
1925 self.assertRaises(TypeError, connection.renegotiate, None)
1926
1927
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001928 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001929 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001930 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001931 any arguments.
1932 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001933 connection = Connection(Context(TLSv1_METHOD), None)
1934 self.assertRaises(TypeError, connection.total_renegotiations, None)
1935
1936
1937 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001938 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001939 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001940 renegotiations have happened.
1941 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001942 connection = Connection(Context(TLSv1_METHOD), None)
1943 self.assertEquals(connection.total_renegotiations(), 0)
1944
1945
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001946# def test_renegotiate(self):
1947# """
1948# """
1949# server, client = self._loopback()
1950
1951# server.send("hello world")
1952# self.assertEquals(client.recv(len("hello world")), "hello world")
1953
1954# self.assertEquals(server.total_renegotiations(), 0)
1955# self.assertTrue(server.renegotiate())
1956
1957# server.setblocking(False)
1958# client.setblocking(False)
1959# while server.renegotiate_pending():
1960# client.do_handshake()
1961# server.do_handshake()
1962
1963# self.assertEquals(server.total_renegotiations(), 1)
1964
1965
1966
1967
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001968class ErrorTests(TestCase):
1969 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001970 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001971 """
1972 def test_type(self):
1973 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001974 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001975 """
1976 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05001977 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05001978
1979
1980
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001981class ConstantsTests(TestCase):
1982 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001983 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001984
1985 These are values defined by OpenSSL intended only to be used as flags to
1986 OpenSSL APIs. The only assertions it seems can be made about them is
1987 their values.
1988 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001989 # unittest.TestCase has no skip mechanism
1990 if OP_NO_QUERY_MTU is not None:
1991 def test_op_no_query_mtu(self):
1992 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001993 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001994 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001995 """
1996 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
1997 else:
1998 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001999
2000
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002001 if OP_COOKIE_EXCHANGE is not None:
2002 def test_op_cookie_exchange(self):
2003 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002004 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002005 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002006 """
2007 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
2008 else:
2009 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002010
2011
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002012 if OP_NO_TICKET is not None:
2013 def test_op_no_ticket(self):
2014 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002015 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002016 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002017 """
2018 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04002019 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002020 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05002021
2022
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002023 if OP_NO_COMPRESSION is not None:
2024 def test_op_no_compression(self):
2025 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002026 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
2027 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002028 """
2029 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
2030 else:
2031 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
2032
2033
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002034 def test_sess_cache_off(self):
2035 """
2036 The value of L{OpenSSL.SSL.SESS_CACHE_OFF} 0x0, the value of
2037 L{SSL_SESS_CACHE_OFF} defined by I{openssl/ssl.h}.
2038 """
2039 self.assertEqual(0x0, SESS_CACHE_OFF)
2040
2041
2042 def test_sess_cache_client(self):
2043 """
2044 The value of L{OpenSSL.SSL.SESS_CACHE_CLIENT} 0x1, the value of
2045 L{SSL_SESS_CACHE_CLIENT} defined by I{openssl/ssl.h}.
2046 """
2047 self.assertEqual(0x1, SESS_CACHE_CLIENT)
2048
2049
2050 def test_sess_cache_server(self):
2051 """
2052 The value of L{OpenSSL.SSL.SESS_CACHE_SERVER} 0x2, the value of
2053 L{SSL_SESS_CACHE_SERVER} defined by I{openssl/ssl.h}.
2054 """
2055 self.assertEqual(0x2, SESS_CACHE_SERVER)
2056
2057
2058 def test_sess_cache_both(self):
2059 """
2060 The value of L{OpenSSL.SSL.SESS_CACHE_BOTH} 0x3, the value of
2061 L{SSL_SESS_CACHE_BOTH} defined by I{openssl/ssl.h}.
2062 """
2063 self.assertEqual(0x3, SESS_CACHE_BOTH)
2064
2065
2066 def test_sess_cache_no_auto_clear(self):
2067 """
2068 The value of L{OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR} 0x80, the value of
2069 L{SSL_SESS_CACHE_NO_AUTO_CLEAR} defined by I{openssl/ssl.h}.
2070 """
2071 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
2072
2073
2074 def test_sess_cache_no_internal_lookup(self):
2075 """
2076 The value of L{OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP} 0x100, the
2077 value of L{SSL_SESS_CACHE_NO_INTERNAL_LOOKUP} defined by
2078 I{openssl/ssl.h}.
2079 """
2080 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
2081
2082
2083 def test_sess_cache_no_internal_store(self):
2084 """
2085 The value of L{OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE} 0x200, the
2086 value of L{SSL_SESS_CACHE_NO_INTERNAL_STORE} defined by
2087 I{openssl/ssl.h}.
2088 """
2089 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
2090
2091
2092 def test_sess_cache_no_internal(self):
2093 """
2094 The value of L{OpenSSL.SSL.SESS_CACHE_NO_INTERNAL} 0x300, the value of
2095 L{SSL_SESS_CACHE_NO_INTERNAL} defined by I{openssl/ssl.h}.
2096 """
2097 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
2098
2099
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04002100
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002101class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05002102 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002103 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05002104 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002105 def _server(self, sock):
2106 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002107 Create a new server-side SSL :py:obj:`Connection` object wrapped around
2108 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002109 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002110 # Create the server side Connection. This is mostly setup boilerplate
2111 # - use TLSv1, use a particular certificate, etc.
2112 server_ctx = Context(TLSv1_METHOD)
2113 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2114 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2115 server_store = server_ctx.get_cert_store()
2116 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2117 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2118 server_ctx.check_privatekey()
2119 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002120 # Here the Connection is actually created. If None is passed as the 2nd
2121 # parameter, it indicates a memory BIO should be created.
2122 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002123 server_conn.set_accept_state()
2124 return server_conn
2125
2126
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002127 def _client(self, sock):
2128 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002129 Create a new client-side SSL :py:obj:`Connection` object wrapped around
2130 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002131 """
2132 # Now create the client side Connection. Similar boilerplate to the
2133 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002134 client_ctx = Context(TLSv1_METHOD)
2135 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2136 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2137 client_store = client_ctx.get_cert_store()
2138 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
2139 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
2140 client_ctx.check_privatekey()
2141 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002142 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002143 client_conn.set_connect_state()
2144 return client_conn
2145
2146
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002147 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002148 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002149 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002150 reading from the output of each and writing those bytes to the input of
2151 the other and in this way establish a connection and exchange
2152 application-level bytes with each other.
2153 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002154 server_conn = self._server(None)
2155 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002156
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002157 # There should be no key or nonces yet.
2158 self.assertIdentical(server_conn.master_key(), None)
2159 self.assertIdentical(server_conn.client_random(), None)
2160 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002161
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002162 # First, the handshake needs to happen. We'll deliver bytes back and
2163 # forth between the client and server until neither of them feels like
2164 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002165 self.assertIdentical(
2166 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002167
2168 # Now that the handshake is done, there should be a key and nonces.
2169 self.assertNotIdentical(server_conn.master_key(), None)
2170 self.assertNotIdentical(server_conn.client_random(), None)
2171 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04002172 self.assertEquals(server_conn.client_random(), client_conn.client_random())
2173 self.assertEquals(server_conn.server_random(), client_conn.server_random())
2174 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
2175 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002176
2177 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002178 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05002179
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002180 server_conn.write(important_message)
2181 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002182 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002183 (client_conn, important_message))
2184
2185 client_conn.write(important_message[::-1])
2186 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002187 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002188 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05002189
2190
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002191 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05002192 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002193 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002194
2195 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09002196 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002197 this test fails, there must be a problem outside the memory BIO
2198 code, as no memory BIO is involved here). Even though this isn't a
2199 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05002200 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04002201 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05002202
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002203 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05002204 client_conn.send(important_message)
2205 msg = server_conn.recv(1024)
2206 self.assertEqual(msg, important_message)
2207
2208 # Again in the other direction, just for fun.
2209 important_message = important_message[::-1]
2210 server_conn.send(important_message)
2211 msg = client_conn.recv(1024)
2212 self.assertEqual(msg, important_message)
2213
2214
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04002215 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05002216 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002217 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
2218 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05002219 """
2220 context = Context(SSLv3_METHOD)
2221 client = socket()
2222 clientSSL = Connection(context, client)
2223 self.assertRaises( TypeError, clientSSL.bio_read, 100)
2224 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04002225 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002226
2227
2228 def test_outgoingOverflow(self):
2229 """
2230 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002231 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002232 returned and that many bytes from the beginning of the input can be
2233 read from the other end of the connection.
2234 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002235 server = self._server(None)
2236 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002237
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002238 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002239
2240 size = 2 ** 15
2241 sent = client.send("x" * size)
2242 # Sanity check. We're trying to test what happens when the entire
2243 # input can't be sent. If the entire input was sent, this test is
2244 # meaningless.
2245 self.assertTrue(sent < size)
2246
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002247 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002248 self.assertIdentical(receiver, server)
2249
2250 # We can rely on all of these bytes being received at once because
2251 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
2252 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002253
2254
2255 def test_shutdown(self):
2256 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002257 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
2258 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002259 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002260 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002261 server.bio_shutdown()
2262 e = self.assertRaises(Error, server.recv, 1024)
2263 # We don't want WantReadError or ZeroReturnError or anything - it's a
2264 # handshake failure.
2265 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002266
2267
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002268 def test_unexpectedEndOfFile(self):
2269 """
2270 If the connection is lost before an orderly SSL shutdown occurs,
2271 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
2272 "Unexpected EOF".
2273 """
2274 server_conn, client_conn = self._loopback()
2275 client_conn.sock_shutdown(SHUT_RDWR)
2276 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
2277 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
2278
2279
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002280 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002281 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002282 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 -04002283
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002284 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002285 before the client and server are connected to each other. This
2286 function should specify a list of CAs for the server to send to the
2287 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09002288 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002289 times.
2290 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002291 server = self._server(None)
2292 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002293 self.assertEqual(client.get_client_ca_list(), [])
2294 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002295 ctx = server.get_context()
2296 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002297 self.assertEqual(client.get_client_ca_list(), [])
2298 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002299 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002300 self.assertEqual(client.get_client_ca_list(), expected)
2301 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002302
2303
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002304 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002305 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002306 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002307 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002308 """
2309 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002310 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
2311 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
2312 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002313
2314
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002315 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002316 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002317 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002318 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09002319 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002320 after the connection is set up.
2321 """
2322 def no_ca(ctx):
2323 ctx.set_client_ca_list([])
2324 return []
2325 self._check_client_ca_list(no_ca)
2326
2327
2328 def test_set_one_ca_list(self):
2329 """
2330 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002331 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002332 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002333 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002334 X509Name after the connection is set up.
2335 """
2336 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2337 cadesc = cacert.get_subject()
2338 def single_ca(ctx):
2339 ctx.set_client_ca_list([cadesc])
2340 return [cadesc]
2341 self._check_client_ca_list(single_ca)
2342
2343
2344 def test_set_multiple_ca_list(self):
2345 """
2346 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002347 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002348 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002349 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002350 X509Names after the connection is set up.
2351 """
2352 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2353 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2354
2355 sedesc = secert.get_subject()
2356 cldesc = clcert.get_subject()
2357
2358 def multiple_ca(ctx):
2359 L = [sedesc, cldesc]
2360 ctx.set_client_ca_list(L)
2361 return L
2362 self._check_client_ca_list(multiple_ca)
2363
2364
2365 def test_reset_ca_list(self):
2366 """
2367 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09002368 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002369 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002370 """
2371 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2372 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2373 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2374
2375 cadesc = cacert.get_subject()
2376 sedesc = secert.get_subject()
2377 cldesc = clcert.get_subject()
2378
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002379 def changed_ca(ctx):
2380 ctx.set_client_ca_list([sedesc, cldesc])
2381 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002382 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002383 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002384
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002385
2386 def test_mutated_ca_list(self):
2387 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002388 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002389 afterwards, this does not affect the list of CA names sent to the
2390 client.
2391 """
2392 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2393 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2394
2395 cadesc = cacert.get_subject()
2396 sedesc = secert.get_subject()
2397
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002398 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002399 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002400 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002401 L.append(sedesc)
2402 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002403 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002404
2405
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002406 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002407 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002408 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002409 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002410 """
2411 ctx = Context(TLSv1_METHOD)
2412 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002413 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002414 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002415 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002416
2417
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002418 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002419 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002420 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09002421 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002422 """
2423 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2424 cadesc = cacert.get_subject()
2425 def single_ca(ctx):
2426 ctx.add_client_ca(cacert)
2427 return [cadesc]
2428 self._check_client_ca_list(single_ca)
2429
2430
2431 def test_multiple_add_client_ca(self):
2432 """
2433 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09002434 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002435 """
2436 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2437 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2438
2439 cadesc = cacert.get_subject()
2440 sedesc = secert.get_subject()
2441
2442 def multiple_ca(ctx):
2443 ctx.add_client_ca(cacert)
2444 ctx.add_client_ca(secert)
2445 return [cadesc, sedesc]
2446 self._check_client_ca_list(multiple_ca)
2447
2448
2449 def test_set_and_add_client_ca(self):
2450 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002451 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
2452 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002453 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002454 """
2455 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2456 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2457 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2458
2459 cadesc = cacert.get_subject()
2460 sedesc = secert.get_subject()
2461 cldesc = clcert.get_subject()
2462
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002463 def mixed_set_add_ca(ctx):
2464 ctx.set_client_ca_list([cadesc, sedesc])
2465 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002466 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002467 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002468
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002469
2470 def test_set_after_add_client_ca(self):
2471 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002472 A call to :py:obj:`Context.set_client_ca_list` after a call to
2473 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002474 call with the names specified by the latter cal.
2475 """
2476 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2477 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2478 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2479
2480 cadesc = cacert.get_subject()
2481 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002482
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002483 def set_replaces_add_ca(ctx):
2484 ctx.add_client_ca(clcert)
2485 ctx.set_client_ca_list([cadesc])
2486 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002487 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002488 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002489
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002490
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002491
2492class ConnectionBIOTests(TestCase):
2493 """
2494 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
2495 """
2496 def test_wantReadError(self):
2497 """
2498 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
2499 if there are no bytes available to be read from the BIO.
2500 """
2501 ctx = Context(TLSv1_METHOD)
2502 conn = Connection(ctx, None)
2503 self.assertRaises(WantReadError, conn.bio_read, 1024)
2504
2505
2506
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04002507class InfoConstantTests(TestCase):
2508 """
2509 Tests for assorted constants exposed for use in info callbacks.
2510 """
2511 def test_integers(self):
2512 """
2513 All of the info constants are integers.
2514
2515 This is a very weak test. It would be nice to have one that actually
2516 verifies that as certain info events happen, the value passed to the
2517 info callback matches up with the constant exposed by OpenSSL.SSL.
2518 """
2519 for const in [
2520 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
2521 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
2522 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
2523 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
2524 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
2525 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
2526
2527 self.assertTrue(isinstance(const, int))
2528
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02002529
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002530if __name__ == '__main__':
2531 main()