blob: c9417b9232d834aebe0b420ff0b930d52f41788f [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 Calderone8322d782010-09-17 19:22:31 -04009from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040010from sys import platform, version_info
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -040011from socket import error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040012from os import makedirs
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -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 Calderone7526d172010-09-09 17:55:31 -040018from OpenSSL.crypto import PKey, X509, X509Extension
19from 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 Calderone30c09ea2008-03-21 17:04:05 -040025from OpenSSL.SSL import SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD
Jean-Paul Calderone68649052009-07-17 21:14:27 -040026from OpenSSL.SSL import OP_NO_SSLv2, OP_NO_SSLv3, OP_SINGLE_DH_USE
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040027from OpenSSL.SSL import (
28 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040029
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040030from OpenSSL.SSL import (
31 Error, SysCallError, WantReadError, ZeroReturnError, SSLeay_version)
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040032from OpenSSL.SSL import Context, ContextType, Connection, ConnectionType
33
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -040034from OpenSSL.test.util import TestCase, bytes, b
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040035from OpenSSL.test.test_crypto import (
36 cleartextCertificatePEM, cleartextPrivateKeyPEM)
37from OpenSSL.test.test_crypto import (
38 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
39 root_cert_pem)
40
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050041try:
42 from OpenSSL.SSL import OP_NO_QUERY_MTU
43except ImportError:
44 OP_NO_QUERY_MTU = None
45try:
46 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
47except ImportError:
48 OP_COOKIE_EXCHANGE = None
49try:
50 from OpenSSL.SSL import OP_NO_TICKET
51except ImportError:
52 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040053
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040054try:
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -040055 from OpenSSL.SSL import OP_NO_COMPRESSION
56except ImportError:
57 OP_NO_COMPRESSION = None
58
59try:
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040060 from OpenSSL.SSL import MODE_RELEASE_BUFFERS
61except ImportError:
62 MODE_RELEASE_BUFFERS = None
63
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040064from OpenSSL.SSL import (
65 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
66 SSL_ST_OK, SSL_ST_RENEGOTIATE,
67 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
68 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
69 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
70 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040071
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040072# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
73# to use)
74dhparam = """\
75-----BEGIN DH PARAMETERS-----
76MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
77-----END DH PARAMETERS-----
78"""
79
80
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040081def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040082 return ok
83
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040084
Rick Deanb1ccd562009-07-09 23:52:39 -050085def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040086 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -040087 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040088 """
89 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -050090 port = socket()
91 port.bind(('', 0))
92 port.listen(1)
93 client = socket()
94 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -040095 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -040096 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -050097 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -050098
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040099 # Let's pass some unencrypted data to make sure our socket connection is
100 # fine. Just one byte, so we don't have to worry about buffers getting
101 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400102 server.send(b("x"))
103 assert client.recv(1024) == b("x")
104 client.send(b("y"))
105 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500106
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400107 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400108 server.setblocking(False)
109 client.setblocking(False)
110
Rick Deanb1ccd562009-07-09 23:52:39 -0500111 return (server, client)
112
113
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400114
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400115def handshake(client, server):
116 conns = [client, server]
117 while conns:
118 for conn in conns:
119 try:
120 conn.do_handshake()
121 except WantReadError:
122 pass
123 else:
124 conns.remove(conn)
125
126
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400127def _create_certificate_chain():
128 """
129 Construct and return a chain of certificates.
130
131 1. A new self-signed certificate authority certificate (cacert)
132 2. A new intermediate certificate signed by cacert (icert)
133 3. A new server certificate signed by icert (scert)
134 """
135 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
136
137 # Step 1
138 cakey = PKey()
139 cakey.generate_key(TYPE_RSA, 512)
140 cacert = X509()
141 cacert.get_subject().commonName = "Authority Certificate"
142 cacert.set_issuer(cacert.get_subject())
143 cacert.set_pubkey(cakey)
144 cacert.set_notBefore(b("20000101000000Z"))
145 cacert.set_notAfter(b("20200101000000Z"))
146 cacert.add_extensions([caext])
147 cacert.set_serial_number(0)
148 cacert.sign(cakey, "sha1")
149
150 # Step 2
151 ikey = PKey()
152 ikey.generate_key(TYPE_RSA, 512)
153 icert = X509()
154 icert.get_subject().commonName = "Intermediate Certificate"
155 icert.set_issuer(cacert.get_subject())
156 icert.set_pubkey(ikey)
157 icert.set_notBefore(b("20000101000000Z"))
158 icert.set_notAfter(b("20200101000000Z"))
159 icert.add_extensions([caext])
160 icert.set_serial_number(0)
161 icert.sign(cakey, "sha1")
162
163 # Step 3
164 skey = PKey()
165 skey.generate_key(TYPE_RSA, 512)
166 scert = X509()
167 scert.get_subject().commonName = "Server Certificate"
168 scert.set_issuer(icert.get_subject())
169 scert.set_pubkey(skey)
170 scert.set_notBefore(b("20000101000000Z"))
171 scert.set_notAfter(b("20200101000000Z"))
172 scert.add_extensions([
173 X509Extension(b('basicConstraints'), True, b('CA:false'))])
174 scert.set_serial_number(0)
175 scert.sign(ikey, "sha1")
176
177 return [(cakey, cacert), (ikey, icert), (skey, scert)]
178
179
180
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400181class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400182 """
183 Helper mixin which defines methods for creating a connected socket pair and
184 for forcing two connected SSL sockets to talk to each other via memory BIOs.
185 """
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400186 def _loopback(self):
187 (server, client) = socket_pair()
188
189 ctx = Context(TLSv1_METHOD)
190 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
191 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
192 server = Connection(ctx, server)
193 server.set_accept_state()
194 client = Connection(Context(TLSv1_METHOD), client)
195 client.set_connect_state()
196
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400197 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400198
199 server.setblocking(True)
200 client.setblocking(True)
201 return server, client
202
203
204 def _interactInMemory(self, client_conn, server_conn):
205 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900206 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400207 objects. Copy bytes back and forth between their send/receive buffers
208 for as long as there is anything to copy. When there is nothing more
Jonathan Ballet648875f2011-07-16 14:14:58 +0900209 to copy, return :py:obj:`None`. If one of them actually manages to deliver
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400210 some application bytes, return a two-tuple of the connection from which
211 the bytes were read and the bytes themselves.
212 """
213 wrote = True
214 while wrote:
215 # Loop until neither side has anything to say
216 wrote = False
217
218 # Copy stuff from each side's send buffer to the other side's
219 # receive buffer.
220 for (read, write) in [(client_conn, server_conn),
221 (server_conn, client_conn)]:
222
223 # Give the side a chance to generate some more bytes, or
224 # succeed.
225 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400226 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400227 except WantReadError:
228 # It didn't succeed, so we'll hope it generated some
229 # output.
230 pass
231 else:
232 # It did succeed, so we'll stop now and let the caller deal
233 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400234 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400235
236 while True:
237 # Keep copying as long as there's more stuff there.
238 try:
239 dirty = read.bio_read(4096)
240 except WantReadError:
241 # Okay, nothing more waiting to be sent. Stop
242 # processing this send buffer.
243 break
244 else:
245 # Keep track of the fact that someone generated some
246 # output.
247 wrote = True
248 write.bio_write(dirty)
249
250
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400251
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400252class VersionTests(TestCase):
253 """
254 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900255 :py:obj:`OpenSSL.SSL.SSLeay_version` and
256 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400257 """
258 def test_OPENSSL_VERSION_NUMBER(self):
259 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900260 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400261 byte and the patch, fix, minor, and major versions in the
262 nibbles above that.
263 """
264 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
265
266
267 def test_SSLeay_version(self):
268 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900269 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400270 one of a number of version strings based on that indicator.
271 """
272 versions = {}
273 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
274 SSLEAY_PLATFORM, SSLEAY_DIR]:
275 version = SSLeay_version(t)
276 versions[version] = t
277 self.assertTrue(isinstance(version, bytes))
278 self.assertEqual(len(versions), 5)
279
280
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400281
282class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400283 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900284 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400285 """
286 def test_method(self):
287 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900288 :py:obj:`Context` can be instantiated with one of :py:obj:`SSLv2_METHOD`,
289 :py:obj:`SSLv3_METHOD`, :py:obj:`SSLv23_METHOD`, or :py:obj:`TLSv1_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400290 """
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400291 for meth in [SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400292 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400293
294 try:
295 Context(SSLv2_METHOD)
296 except ValueError:
297 # Some versions of OpenSSL have SSLv2, some don't.
298 # Difficult to say in advance.
299 pass
300
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400301 self.assertRaises(TypeError, Context, "")
302 self.assertRaises(ValueError, Context, 10)
303
304
Rick Deane15b1472009-07-09 15:53:42 -0500305 def test_type(self):
306 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900307 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400308 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500309 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400310 self.assertIdentical(Context, ContextType)
311 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500312
313
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400314 def test_use_privatekey(self):
315 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900316 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400317 """
318 key = PKey()
319 key.generate_key(TYPE_RSA, 128)
320 ctx = Context(TLSv1_METHOD)
321 ctx.use_privatekey(key)
322 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400323
324
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400325 def test_set_app_data_wrong_args(self):
326 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900327 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called with other than
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400328 one argument.
329 """
330 context = Context(TLSv1_METHOD)
331 self.assertRaises(TypeError, context.set_app_data)
332 self.assertRaises(TypeError, context.set_app_data, None, None)
333
334
335 def test_get_app_data_wrong_args(self):
336 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900337 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400338 arguments.
339 """
340 context = Context(TLSv1_METHOD)
341 self.assertRaises(TypeError, context.get_app_data, None)
342
343
344 def test_app_data(self):
345 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900346 :py:obj:`Context.set_app_data` stores an object for later retrieval using
347 :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400348 """
349 app_data = object()
350 context = Context(TLSv1_METHOD)
351 context.set_app_data(app_data)
352 self.assertIdentical(context.get_app_data(), app_data)
353
354
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400355 def test_set_options_wrong_args(self):
356 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900357 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with the wrong
358 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400359 """
360 context = Context(TLSv1_METHOD)
361 self.assertRaises(TypeError, context.set_options)
362 self.assertRaises(TypeError, context.set_options, None)
363 self.assertRaises(TypeError, context.set_options, 1, None)
364
365
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300366 def test_set_mode_wrong_args(self):
367 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400368 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with the wrong
369 number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300370 """
371 context = Context(TLSv1_METHOD)
372 self.assertRaises(TypeError, context.set_mode)
373 self.assertRaises(TypeError, context.set_mode, None)
374 self.assertRaises(TypeError, context.set_mode, 1, None)
375
376
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400377 if MODE_RELEASE_BUFFERS is not None:
378 def test_set_mode(self):
379 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400380 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the newly
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400381 set mode.
382 """
383 context = Context(TLSv1_METHOD)
384 self.assertTrue(
385 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
386 else:
387 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
388
389
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400390 def test_set_timeout_wrong_args(self):
391 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900392 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with the wrong
393 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400394 """
395 context = Context(TLSv1_METHOD)
396 self.assertRaises(TypeError, context.set_timeout)
397 self.assertRaises(TypeError, context.set_timeout, None)
398 self.assertRaises(TypeError, context.set_timeout, 1, None)
399
400
401 def test_get_timeout_wrong_args(self):
402 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900403 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400404 """
405 context = Context(TLSv1_METHOD)
406 self.assertRaises(TypeError, context.get_timeout, None)
407
408
409 def test_timeout(self):
410 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900411 :py:obj:`Context.set_timeout` sets the session timeout for all connections
412 created using the context object. :py:obj:`Context.get_timeout` retrieves this
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400413 value.
414 """
415 context = Context(TLSv1_METHOD)
416 context.set_timeout(1234)
417 self.assertEquals(context.get_timeout(), 1234)
418
419
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400420 def test_set_verify_depth_wrong_args(self):
421 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900422 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called with the wrong
423 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400424 """
425 context = Context(TLSv1_METHOD)
426 self.assertRaises(TypeError, context.set_verify_depth)
427 self.assertRaises(TypeError, context.set_verify_depth, None)
428 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
429
430
431 def test_get_verify_depth_wrong_args(self):
432 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900433 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400434 """
435 context = Context(TLSv1_METHOD)
436 self.assertRaises(TypeError, context.get_verify_depth, None)
437
438
439 def test_verify_depth(self):
440 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900441 :py:obj:`Context.set_verify_depth` sets the number of certificates in a chain
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400442 to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900443 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400444 """
445 context = Context(TLSv1_METHOD)
446 context.set_verify_depth(11)
447 self.assertEquals(context.get_verify_depth(), 11)
448
449
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400450 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400451 """
452 Write a new private key out to a new file, encrypted using the given
453 passphrase. Return the path to the new file.
454 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400455 key = PKey()
456 key.generate_key(TYPE_RSA, 128)
457 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400458 fObj = open(pemFile, 'w')
459 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
460 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400461 fObj.close()
462 return pemFile
463
464
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400465 def test_set_passwd_cb_wrong_args(self):
466 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900467 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called with the
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400468 wrong arguments or with a non-callable first argument.
469 """
470 context = Context(TLSv1_METHOD)
471 self.assertRaises(TypeError, context.set_passwd_cb)
472 self.assertRaises(TypeError, context.set_passwd_cb, None)
473 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
474
475
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400476 def test_set_passwd_cb(self):
477 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900478 :py:obj:`Context.set_passwd_cb` accepts a callable which will be invoked when
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400479 a private key is loaded from an encrypted PEM.
480 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400481 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400482 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400483 calledWith = []
484 def passphraseCallback(maxlen, verify, extra):
485 calledWith.append((maxlen, verify, extra))
486 return passphrase
487 context = Context(TLSv1_METHOD)
488 context.set_passwd_cb(passphraseCallback)
489 context.use_privatekey_file(pemFile)
490 self.assertTrue(len(calledWith), 1)
491 self.assertTrue(isinstance(calledWith[0][0], int))
492 self.assertTrue(isinstance(calledWith[0][1], int))
493 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400494
495
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400496 def test_passwd_callback_exception(self):
497 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900498 :py:obj:`Context.use_privatekey_file` propagates any exception raised by the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400499 passphrase callback.
500 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400501 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400502 def passphraseCallback(maxlen, verify, extra):
503 raise RuntimeError("Sorry, I am a fail.")
504
505 context = Context(TLSv1_METHOD)
506 context.set_passwd_cb(passphraseCallback)
507 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
508
509
510 def test_passwd_callback_false(self):
511 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900512 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400513 passphrase callback returns a false value.
514 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400515 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400516 def passphraseCallback(maxlen, verify, extra):
517 return None
518
519 context = Context(TLSv1_METHOD)
520 context.set_passwd_cb(passphraseCallback)
521 self.assertRaises(Error, context.use_privatekey_file, pemFile)
522
523
524 def test_passwd_callback_non_string(self):
525 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900526 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400527 passphrase callback returns a true non-string value.
528 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400529 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400530 def passphraseCallback(maxlen, verify, extra):
531 return 10
532
533 context = Context(TLSv1_METHOD)
534 context.set_passwd_cb(passphraseCallback)
535 self.assertRaises(Error, context.use_privatekey_file, pemFile)
536
537
538 def test_passwd_callback_too_long(self):
539 """
540 If the passphrase returned by the passphrase callback returns a string
541 longer than the indicated maximum length, it is truncated.
542 """
543 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400544 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400545 pemFile = self._write_encrypted_pem(passphrase)
546 def passphraseCallback(maxlen, verify, extra):
547 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400548 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400549
550 context = Context(TLSv1_METHOD)
551 context.set_passwd_cb(passphraseCallback)
552 # This shall succeed because the truncated result is the correct
553 # passphrase.
554 context.use_privatekey_file(pemFile)
555
556
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400557 def test_set_info_callback(self):
558 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900559 :py:obj:`Context.set_info_callback` accepts a callable which will be invoked
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400560 when certain information about an SSL connection is available.
561 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500562 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400563
564 clientSSL = Connection(Context(TLSv1_METHOD), client)
565 clientSSL.set_connect_state()
566
567 called = []
568 def info(conn, where, ret):
569 called.append((conn, where, ret))
570 context = Context(TLSv1_METHOD)
571 context.set_info_callback(info)
572 context.use_certificate(
573 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
574 context.use_privatekey(
575 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
576
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400577 serverSSL = Connection(context, server)
578 serverSSL.set_accept_state()
579
580 while not called:
581 for ssl in clientSSL, serverSSL:
582 try:
583 ssl.do_handshake()
584 except WantReadError:
585 pass
586
587 # Kind of lame. Just make sure it got called somehow.
588 self.assertTrue(called)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400589
590
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400591 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400592 """
593 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400594 its :py:obj:`load_verify_locations` method with the given arguments.
595 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400596 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500597 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400598
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400599 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400600 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400601 # Require that the server certificate verify properly or the
602 # connection will fail.
603 clientContext.set_verify(
604 VERIFY_PEER,
605 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
606
607 clientSSL = Connection(clientContext, client)
608 clientSSL.set_connect_state()
609
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400610 serverContext = Context(TLSv1_METHOD)
611 serverContext.use_certificate(
612 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
613 serverContext.use_privatekey(
614 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
615
616 serverSSL = Connection(serverContext, server)
617 serverSSL.set_accept_state()
618
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400619 # Without load_verify_locations above, the handshake
620 # will fail:
621 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
622 # 'certificate verify failed')]
623 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400624
625 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400626 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400627
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500628
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400629 def test_load_verify_file(self):
630 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900631 :py:obj:`Context.load_verify_locations` accepts a file name and uses the
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400632 certificates within for verification purposes.
633 """
634 cafile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400635 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400636 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400637 fObj.close()
638
639 self._load_verify_locations_test(cafile)
640
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400641
642 def test_load_verify_invalid_file(self):
643 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900644 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when passed a
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400645 non-existent cafile.
646 """
647 clientContext = Context(TLSv1_METHOD)
648 self.assertRaises(
649 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400650
651
652 def test_load_verify_directory(self):
653 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900654 :py:obj:`Context.load_verify_locations` accepts a directory name and uses
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400655 the certificates within for verification purposes.
656 """
657 capath = self.mktemp()
658 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400659 # Hash values computed manually with c_rehash to avoid depending on
660 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
661 # from OpenSSL 1.0.0.
662 for name in ['c7adac82.0', 'c3705638.0']:
663 cafile = join(capath, name)
664 fObj = open(cafile, 'w')
665 fObj.write(cleartextCertificatePEM.decode('ascii'))
666 fObj.close()
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400667
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400668 self._load_verify_locations_test(None, capath)
669
670
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400671 def test_load_verify_locations_wrong_args(self):
672 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900673 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if called with
674 the wrong number of arguments or with non-:py:obj:`str` arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400675 """
676 context = Context(TLSv1_METHOD)
677 self.assertRaises(TypeError, context.load_verify_locations)
678 self.assertRaises(TypeError, context.load_verify_locations, object())
679 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
680 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
681
682
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400683 if platform == "win32":
684 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400685 "See LP#404343 and LP#404344."
686 else:
687 def test_set_default_verify_paths(self):
688 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900689 :py:obj:`Context.set_default_verify_paths` causes the platform-specific CA
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400690 certificate locations to be used for verification purposes.
691 """
692 # Testing this requires a server with a certificate signed by one of
693 # the CAs in the platform CA location. Getting one of those costs
694 # money. Fortunately (or unfortunately, depending on your
695 # perspective), it's easy to think of a public server on the
696 # internet which has such a certificate. Connecting to the network
697 # in a unit test is bad, but it's the only way I can think of to
698 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400699
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400700 # Arg, verisign.com doesn't speak TLSv1
701 context = Context(SSLv3_METHOD)
702 context.set_default_verify_paths()
703 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +0200704 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400705 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400706
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400707 client = socket()
708 client.connect(('verisign.com', 443))
709 clientSSL = Connection(context, client)
710 clientSSL.set_connect_state()
711 clientSSL.do_handshake()
712 clientSSL.send('GET / HTTP/1.0\r\n\r\n')
713 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400714
715
716 def test_set_default_verify_paths_signature(self):
717 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900718 :py:obj:`Context.set_default_verify_paths` takes no arguments and raises
719 :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400720 """
721 context = Context(TLSv1_METHOD)
722 self.assertRaises(TypeError, context.set_default_verify_paths, None)
723 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
724 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500725
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400726
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500727 def test_add_extra_chain_cert_invalid_cert(self):
728 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900729 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if called with
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500730 other than one argument or if called with an object which is not an
Jonathan Ballet648875f2011-07-16 14:14:58 +0900731 instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500732 """
733 context = Context(TLSv1_METHOD)
734 self.assertRaises(TypeError, context.add_extra_chain_cert)
735 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
736 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
737
738
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400739 def _handshake_test(self, serverContext, clientContext):
740 """
741 Verify that a client and server created with the given contexts can
742 successfully handshake and communicate.
743 """
744 serverSocket, clientSocket = socket_pair()
745
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400746 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400747 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400748
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400749 client = Connection(clientContext, clientSocket)
750 client.set_connect_state()
751
752 # Make them talk to each other.
753 # self._interactInMemory(client, server)
754 for i in range(3):
755 for s in [client, server]:
756 try:
757 s.do_handshake()
758 except WantReadError:
759 pass
760
761
762 def test_add_extra_chain_cert(self):
763 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900764 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509` instance to add to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400765 the certificate chain.
766
Jonathan Ballet648875f2011-07-16 14:14:58 +0900767 See :py:obj:`_create_certificate_chain` for the details of the certificate
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400768 chain tested.
769
770 The chain is tested by starting a server with scert and connecting
771 to it with a client which trusts cacert and requires verification to
772 succeed.
773 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400774 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400775 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
776
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400777 # Dump the CA certificate to a file because that's the only way to load
778 # it as a trusted CA in the client context.
779 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400780 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400781 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400782 fObj.close()
783
784 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400785 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400786 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400787 fObj.close()
788
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400789 # Create the server context
790 serverContext = Context(TLSv1_METHOD)
791 serverContext.use_privatekey(skey)
792 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400793 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400794 serverContext.add_extra_chain_cert(icert)
795
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400796 # Create the client
797 clientContext = Context(TLSv1_METHOD)
798 clientContext.set_verify(
799 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
800 clientContext.load_verify_locations('ca.pem')
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400801
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400802 # Try it out.
803 self._handshake_test(serverContext, clientContext)
804
805
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400806 def test_use_certificate_chain_file(self):
807 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900808 :py:obj:`Context.use_certificate_chain_file` reads a certificate chain from
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400809 the specified file.
810
811 The chain is tested by starting a server with scert and connecting
812 to it with a client which trusts cacert and requires verification to
813 succeed.
814 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400815 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400816 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
817
818 # Write out the chain file.
819 chainFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400820 fObj = open(chainFile, 'w')
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400821 # Most specific to least general.
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400822 fObj.write(dump_certificate(FILETYPE_PEM, scert).decode('ascii'))
823 fObj.write(dump_certificate(FILETYPE_PEM, icert).decode('ascii'))
824 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400825 fObj.close()
826
827 serverContext = Context(TLSv1_METHOD)
828 serverContext.use_certificate_chain_file(chainFile)
829 serverContext.use_privatekey(skey)
830
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400831 fObj = open('ca.pem', 'w')
832 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400833 fObj.close()
834
835 clientContext = Context(TLSv1_METHOD)
836 clientContext.set_verify(
837 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
838 clientContext.load_verify_locations('ca.pem')
839
840 self._handshake_test(serverContext, clientContext)
841
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -0400842 # XXX load_client_ca
843 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -0400844
845 def test_get_verify_mode_wrong_args(self):
846 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900847 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -0400848 arguments.
849 """
850 context = Context(TLSv1_METHOD)
851 self.assertRaises(TypeError, context.get_verify_mode, None)
852
853
854 def test_get_verify_mode(self):
855 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900856 :py:obj:`Context.get_verify_mode` returns the verify mode flags previously
857 passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -0400858 """
859 context = Context(TLSv1_METHOD)
860 self.assertEquals(context.get_verify_mode(), 0)
861 context.set_verify(
862 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
863 self.assertEquals(
864 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
865
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400866
867 def test_load_tmp_dh_wrong_args(self):
868 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900869 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
870 number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400871 """
872 context = Context(TLSv1_METHOD)
873 self.assertRaises(TypeError, context.load_tmp_dh)
874 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
875 self.assertRaises(TypeError, context.load_tmp_dh, object())
876
877
878 def test_load_tmp_dh_missing_file(self):
879 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900880 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the specified file
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400881 does not exist.
882 """
883 context = Context(TLSv1_METHOD)
884 self.assertRaises(Error, context.load_tmp_dh, "hello")
885
886
887 def test_load_tmp_dh(self):
888 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900889 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400890 specified file.
891 """
892 context = Context(TLSv1_METHOD)
893 dhfilename = self.mktemp()
894 dhfile = open(dhfilename, "w")
895 dhfile.write(dhparam)
896 dhfile.close()
897 context.load_tmp_dh(dhfilename)
898 # XXX What should I assert here? -exarkun
899
900
901 def test_set_cipher_list(self):
902 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900903 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`str` naming the ciphers which
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400904 connections created with the context object will be able to choose from.
905 """
906 context = Context(TLSv1_METHOD)
907 context.set_cipher_list("hello world:EXP-RC4-MD5")
908 conn = Connection(context, None)
909 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400910
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400911
912
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -0400913class ServerNameCallbackTests(TestCase, _LoopbackMixin):
914 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900915 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
916 :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -0400917 """
918 def test_wrong_args(self):
919 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900920 :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -0400921 with other than one argument.
922 """
923 context = Context(TLSv1_METHOD)
924 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
925 self.assertRaises(
926 TypeError, context.set_tlsext_servername_callback, 1, 2)
927
928 def test_old_callback_forgotten(self):
929 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900930 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -0400931 callback, the one it replaces is dereferenced.
932 """
933 def callback(connection):
934 pass
935
936 def replacement(connection):
937 pass
938
939 context = Context(TLSv1_METHOD)
940 context.set_tlsext_servername_callback(callback)
941
942 tracker = ref(callback)
943 del callback
944
945 context.set_tlsext_servername_callback(replacement)
946 collect()
947 self.assertIdentical(None, tracker())
948
949
950 def test_no_servername(self):
951 """
952 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +0900953 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
954 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -0400955 """
956 args = []
957 def servername(conn):
958 args.append((conn, conn.get_servername()))
959 context = Context(TLSv1_METHOD)
960 context.set_tlsext_servername_callback(servername)
961
962 # Lose our reference to it. The Context is responsible for keeping it
963 # alive now.
964 del servername
965 collect()
966
967 # Necessary to actually accept the connection
968 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
969 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
970
971 # Do a little connection to trigger the logic
972 server = Connection(context, None)
973 server.set_accept_state()
974
975 client = Connection(Context(TLSv1_METHOD), None)
976 client.set_connect_state()
977
978 self._interactInMemory(server, client)
979
980 self.assertEqual([(server, None)], args)
981
982
983 def test_servername(self):
984 """
985 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +0900986 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
987 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -0400988 """
989 args = []
990 def servername(conn):
991 args.append((conn, conn.get_servername()))
992 context = Context(TLSv1_METHOD)
993 context.set_tlsext_servername_callback(servername)
994
995 # Necessary to actually accept the connection
996 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
997 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
998
999 # Do a little connection to trigger the logic
1000 server = Connection(context, None)
1001 server.set_accept_state()
1002
1003 client = Connection(Context(TLSv1_METHOD), None)
1004 client.set_connect_state()
1005 client.set_tlsext_host_name(b("foo1.example.com"))
1006
1007 self._interactInMemory(server, client)
1008
1009 self.assertEqual([(server, b("foo1.example.com"))], args)
1010
1011
1012
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001013class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05001014 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001015 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001016 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001017 # XXX want_write
1018 # XXX want_read
1019 # XXX get_peer_certificate -> None
1020 # XXX sock_shutdown
1021 # XXX master_key -> TypeError
1022 # XXX server_random -> TypeError
1023 # XXX state_string
1024 # XXX connect -> TypeError
1025 # XXX connect_ex -> TypeError
1026 # XXX set_connect_state -> TypeError
1027 # XXX set_accept_state -> TypeError
1028 # XXX renegotiate_pending
1029 # XXX do_handshake -> TypeError
1030 # XXX bio_read -> TypeError
1031 # XXX recv -> TypeError
1032 # XXX send -> TypeError
1033 # XXX bio_write -> TypeError
1034
Rick Deane15b1472009-07-09 15:53:42 -05001035 def test_type(self):
1036 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001037 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001038 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05001039 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001040 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05001041 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001042 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05001043
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001044
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001045 def test_get_context(self):
1046 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001047 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
1048 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001049 """
1050 context = Context(TLSv1_METHOD)
1051 connection = Connection(context, None)
1052 self.assertIdentical(connection.get_context(), context)
1053
1054
1055 def test_get_context_wrong_args(self):
1056 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001057 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001058 arguments.
1059 """
1060 connection = Connection(Context(TLSv1_METHOD), None)
1061 self.assertRaises(TypeError, connection.get_context, None)
1062
1063
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001064 def test_set_context_wrong_args(self):
1065 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001066 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
1067 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001068 than 1.
1069 """
1070 ctx = Context(TLSv1_METHOD)
1071 connection = Connection(ctx, None)
1072 self.assertRaises(TypeError, connection.set_context)
1073 self.assertRaises(TypeError, connection.set_context, object())
1074 self.assertRaises(TypeError, connection.set_context, "hello")
1075 self.assertRaises(TypeError, connection.set_context, 1)
1076 self.assertRaises(TypeError, connection.set_context, 1, 2)
1077 self.assertRaises(
1078 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
1079 self.assertIdentical(ctx, connection.get_context())
1080
1081
1082 def test_set_context(self):
1083 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001084 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001085 for the connection.
1086 """
1087 original = Context(SSLv23_METHOD)
1088 replacement = Context(TLSv1_METHOD)
1089 connection = Connection(original, None)
1090 connection.set_context(replacement)
1091 self.assertIdentical(replacement, connection.get_context())
1092 # Lose our references to the contexts, just in case the Connection isn't
1093 # properly managing its own contributions to their reference counts.
1094 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001095 collect()
1096
1097
1098 def test_set_tlsext_host_name_wrong_args(self):
1099 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001100 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001101 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09001102 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001103 """
1104 conn = Connection(Context(TLSv1_METHOD), None)
1105 self.assertRaises(TypeError, conn.set_tlsext_host_name)
1106 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
1107 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
1108 self.assertRaises(
1109 TypeError, conn.set_tlsext_host_name, b("with\0null"))
1110
1111 if version_info >= (3,):
1112 # On Python 3.x, don't accidentally implicitly convert from text.
1113 self.assertRaises(
1114 TypeError,
1115 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001116
1117
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001118 def test_get_servername_wrong_args(self):
1119 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001120 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001121 arguments.
1122 """
1123 connection = Connection(Context(TLSv1_METHOD), None)
1124 self.assertRaises(TypeError, connection.get_servername, object())
1125 self.assertRaises(TypeError, connection.get_servername, 1)
1126 self.assertRaises(TypeError, connection.get_servername, "hello")
1127
1128
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001129 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001130 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001131 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001132 immediate read.
1133 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001134 connection = Connection(Context(TLSv1_METHOD), None)
1135 self.assertEquals(connection.pending(), 0)
1136
1137
1138 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001139 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001140 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001141 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001142 connection = Connection(Context(TLSv1_METHOD), None)
1143 self.assertRaises(TypeError, connection.pending, None)
1144
1145
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001146 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001147 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001148 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001149 argument or with the wrong number of arguments.
1150 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001151 connection = Connection(Context(TLSv1_METHOD), socket())
1152 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001153 self.assertRaises(TypeError, connection.connect)
1154 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001155
1156
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001157 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001158 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001159 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001160 connect method raises it.
1161 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001162 client = socket()
1163 context = Context(TLSv1_METHOD)
1164 clientSSL = Connection(context, client)
1165 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04001166 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001167
1168
1169 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001170 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001171 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001172 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001173 port = socket()
1174 port.bind(('', 0))
1175 port.listen(3)
1176
1177 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001178 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
1179 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001180
1181
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001182 if platform == "darwin":
1183 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
1184 else:
1185 def test_connect_ex(self):
1186 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001187 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001188 errno instead of raising an exception.
1189 """
1190 port = socket()
1191 port.bind(('', 0))
1192 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001193
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001194 clientSSL = Connection(Context(TLSv1_METHOD), socket())
1195 clientSSL.setblocking(False)
1196 result = clientSSL.connect_ex(port.getsockname())
1197 expected = (EINPROGRESS, EWOULDBLOCK)
1198 self.assertTrue(
1199 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001200
1201
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001202 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001203 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001204 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001205 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001206 connection = Connection(Context(TLSv1_METHOD), socket())
1207 self.assertRaises(TypeError, connection.accept, None)
1208
1209
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001210 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001211 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001212 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
1213 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001214 connection originated from.
1215 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001216 ctx = Context(TLSv1_METHOD)
1217 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1218 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001219 port = socket()
1220 portSSL = Connection(ctx, port)
1221 portSSL.bind(('', 0))
1222 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001223
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001224 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001225
1226 # Calling portSSL.getsockname() here to get the server IP address sounds
1227 # great, but frequently fails on Windows.
1228 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001229
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001230 serverSSL, address = portSSL.accept()
1231
1232 self.assertTrue(isinstance(serverSSL, Connection))
1233 self.assertIdentical(serverSSL.get_context(), ctx)
1234 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001235
1236
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001237 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001238 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001239 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001240 number of arguments or with arguments other than integers.
1241 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001242 connection = Connection(Context(TLSv1_METHOD), None)
1243 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04001244 self.assertRaises(TypeError, connection.get_shutdown, None)
1245 self.assertRaises(TypeError, connection.set_shutdown)
1246 self.assertRaises(TypeError, connection.set_shutdown, None)
1247 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001248
1249
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001250 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001251 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001252 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001253 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001254 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001255 self.assertFalse(server.shutdown())
1256 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001257 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001258 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
1259 client.shutdown()
1260 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
1261 self.assertRaises(ZeroReturnError, server.recv, 1024)
1262 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001263
1264
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001265 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001266 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001267 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001268 process.
1269 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001270 connection = Connection(Context(TLSv1_METHOD), socket())
1271 connection.set_shutdown(RECEIVED_SHUTDOWN)
1272 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1273
1274
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001275 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001276 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001277 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
1278 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001279 with any arguments.
1280 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001281 conn = Connection(Context(TLSv1_METHOD), None)
1282 self.assertRaises(TypeError, conn.get_app_data, None)
1283 self.assertRaises(TypeError, conn.set_app_data)
1284 self.assertRaises(TypeError, conn.set_app_data, None, None)
1285
1286
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001287 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001288 """
1289 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001290 :py:obj:`Connection.set_app_data` and later retrieved with
1291 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001292 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001293 conn = Connection(Context(TLSv1_METHOD), None)
1294 app_data = object()
1295 conn.set_app_data(app_data)
1296 self.assertIdentical(conn.get_app_data(), app_data)
1297
1298
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001299 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001300 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001301 :py:obj:`Connection.makefile` is not implemented and calling that method raises
1302 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001303 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001304 conn = Connection(Context(TLSv1_METHOD), None)
1305 self.assertRaises(NotImplementedError, conn.makefile)
1306
1307
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001308 def test_get_peer_cert_chain_wrong_args(self):
1309 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001310 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001311 arguments.
1312 """
1313 conn = Connection(Context(TLSv1_METHOD), None)
1314 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
1315 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
1316 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
1317 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
1318
1319
1320 def test_get_peer_cert_chain(self):
1321 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001322 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001323 the connected server returned for the certification verification.
1324 """
1325 chain = _create_certificate_chain()
1326 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1327
1328 serverContext = Context(TLSv1_METHOD)
1329 serverContext.use_privatekey(skey)
1330 serverContext.use_certificate(scert)
1331 serverContext.add_extra_chain_cert(icert)
1332 serverContext.add_extra_chain_cert(cacert)
1333 server = Connection(serverContext, None)
1334 server.set_accept_state()
1335
1336 # Create the client
1337 clientContext = Context(TLSv1_METHOD)
1338 clientContext.set_verify(VERIFY_NONE, verify_cb)
1339 client = Connection(clientContext, None)
1340 client.set_connect_state()
1341
1342 self._interactInMemory(client, server)
1343
1344 chain = client.get_peer_cert_chain()
1345 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001346 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001347 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001348 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001349 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001350 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001351 "Authority Certificate", chain[2].get_subject().CN)
1352
1353
1354 def test_get_peer_cert_chain_none(self):
1355 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001356 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001357 certificate chain.
1358 """
1359 ctx = Context(TLSv1_METHOD)
1360 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1361 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1362 server = Connection(ctx, None)
1363 server.set_accept_state()
1364 client = Connection(Context(TLSv1_METHOD), None)
1365 client.set_connect_state()
1366 self._interactInMemory(client, server)
1367 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001368
1369
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001370
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001371class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001372 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001373 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001374 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04001375 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001376 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001377 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001378 arguments.
1379 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001380 connection = Connection(Context(TLSv1_METHOD), None)
1381 self.assertRaises(TypeError, connection.get_cipher_list, None)
1382
1383
1384 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001385 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001386 :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 -04001387 names of the ciphers which might be used.
1388 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001389 connection = Connection(Context(TLSv1_METHOD), None)
1390 ciphers = connection.get_cipher_list()
1391 self.assertTrue(isinstance(ciphers, list))
1392 for cipher in ciphers:
1393 self.assertTrue(isinstance(cipher, str))
1394
1395
1396
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001397class ConnectionSendTests(TestCase, _LoopbackMixin):
1398 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001399 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001400 """
1401 def test_wrong_args(self):
1402 """
1403 When called with arguments other than a single string,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001404 :py:obj:`Connection.send` raises :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001405 """
1406 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05001407 self.assertRaises(TypeError, connection.send)
1408 self.assertRaises(TypeError, connection.send, object())
1409 self.assertRaises(TypeError, connection.send, "foo", "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001410
1411
1412 def test_short_bytes(self):
1413 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001414 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001415 and returns the number of bytes sent.
1416 """
1417 server, client = self._loopback()
1418 count = server.send(b('xy'))
1419 self.assertEquals(count, 2)
1420 self.assertEquals(client.recv(2), b('xy'))
1421
1422 try:
1423 memoryview
1424 except NameError:
1425 "cannot test sending memoryview without memoryview"
1426 else:
1427 def test_short_memoryview(self):
1428 """
1429 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001430 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001431 bytes sent.
1432 """
1433 server, client = self._loopback()
1434 count = server.send(memoryview(b('xy')))
1435 self.assertEquals(count, 2)
1436 self.assertEquals(client.recv(2), b('xy'))
1437
1438
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05001439
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001440class ConnectionSendallTests(TestCase, _LoopbackMixin):
1441 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001442 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001443 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001444 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001445 """
1446 When called with arguments other than a single string,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001447 :py:obj:`Connection.sendall` raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001448 """
1449 connection = Connection(Context(TLSv1_METHOD), None)
1450 self.assertRaises(TypeError, connection.sendall)
1451 self.assertRaises(TypeError, connection.sendall, object())
1452 self.assertRaises(TypeError, connection.sendall, "foo", "bar")
1453
1454
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001455 def test_short(self):
1456 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001457 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001458 it.
1459 """
1460 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001461 server.sendall(b('x'))
1462 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001463
1464
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05001465 try:
1466 memoryview
1467 except NameError:
1468 "cannot test sending memoryview without memoryview"
1469 else:
1470 def test_short_memoryview(self):
1471 """
1472 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001473 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05001474 """
1475 server, client = self._loopback()
1476 server.sendall(memoryview(b('x')))
1477 self.assertEquals(client.recv(1), b('x'))
1478
1479
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001480 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001481 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001482 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001483 it even if this requires multiple calls of an underlying write function.
1484 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001485 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04001486 # Should be enough, underlying SSL_write should only do 16k at a time.
1487 # On Windows, after 32k of bytes the write will block (forever - because
1488 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04001489 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001490 server.sendall(message)
1491 accum = []
1492 received = 0
1493 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001494 data = client.recv(1024)
1495 accum.append(data)
1496 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04001497 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001498
1499
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001500 def test_closed(self):
1501 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001502 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001503 write error from the low level write call.
1504 """
1505 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04001506 server.sock_shutdown(2)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001507 self.assertRaises(SysCallError, server.sendall, "hello, world")
1508
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001509
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001510
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001511class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
1512 """
1513 Tests for SSL renegotiation APIs.
1514 """
1515 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001516 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001517 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001518 arguments.
1519 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001520 connection = Connection(Context(TLSv1_METHOD), None)
1521 self.assertRaises(TypeError, connection.renegotiate, None)
1522
1523
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001524 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001525 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001526 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001527 any arguments.
1528 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001529 connection = Connection(Context(TLSv1_METHOD), None)
1530 self.assertRaises(TypeError, connection.total_renegotiations, None)
1531
1532
1533 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001534 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001535 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001536 renegotiations have happened.
1537 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001538 connection = Connection(Context(TLSv1_METHOD), None)
1539 self.assertEquals(connection.total_renegotiations(), 0)
1540
1541
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001542# def test_renegotiate(self):
1543# """
1544# """
1545# server, client = self._loopback()
1546
1547# server.send("hello world")
1548# self.assertEquals(client.recv(len("hello world")), "hello world")
1549
1550# self.assertEquals(server.total_renegotiations(), 0)
1551# self.assertTrue(server.renegotiate())
1552
1553# server.setblocking(False)
1554# client.setblocking(False)
1555# while server.renegotiate_pending():
1556# client.do_handshake()
1557# server.do_handshake()
1558
1559# self.assertEquals(server.total_renegotiations(), 1)
1560
1561
1562
1563
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001564class ErrorTests(TestCase):
1565 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001566 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001567 """
1568 def test_type(self):
1569 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001570 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001571 """
1572 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05001573 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05001574
1575
1576
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001577class ConstantsTests(TestCase):
1578 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001579 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001580
1581 These are values defined by OpenSSL intended only to be used as flags to
1582 OpenSSL APIs. The only assertions it seems can be made about them is
1583 their values.
1584 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001585 # unittest.TestCase has no skip mechanism
1586 if OP_NO_QUERY_MTU is not None:
1587 def test_op_no_query_mtu(self):
1588 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001589 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001590 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001591 """
1592 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
1593 else:
1594 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001595
1596
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001597 if OP_COOKIE_EXCHANGE is not None:
1598 def test_op_cookie_exchange(self):
1599 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001600 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001601 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001602 """
1603 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
1604 else:
1605 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001606
1607
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001608 if OP_NO_TICKET is not None:
1609 def test_op_no_ticket(self):
1610 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001611 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001612 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001613 """
1614 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04001615 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001616 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05001617
1618
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04001619 if OP_NO_COMPRESSION is not None:
1620 def test_op_no_compression(self):
1621 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001622 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
1623 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04001624 """
1625 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
1626 else:
1627 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
1628
1629
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04001630
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001631class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05001632 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001633 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05001634 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001635 def _server(self, sock):
1636 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001637 Create a new server-side SSL :py:obj:`Connection` object wrapped around
1638 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001639 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001640 # Create the server side Connection. This is mostly setup boilerplate
1641 # - use TLSv1, use a particular certificate, etc.
1642 server_ctx = Context(TLSv1_METHOD)
1643 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
1644 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
1645 server_store = server_ctx.get_cert_store()
1646 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1647 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1648 server_ctx.check_privatekey()
1649 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05001650 # Here the Connection is actually created. If None is passed as the 2nd
1651 # parameter, it indicates a memory BIO should be created.
1652 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001653 server_conn.set_accept_state()
1654 return server_conn
1655
1656
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001657 def _client(self, sock):
1658 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001659 Create a new client-side SSL :py:obj:`Connection` object wrapped around
1660 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001661 """
1662 # Now create the client side Connection. Similar boilerplate to the
1663 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001664 client_ctx = Context(TLSv1_METHOD)
1665 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
1666 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
1667 client_store = client_ctx.get_cert_store()
1668 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
1669 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
1670 client_ctx.check_privatekey()
1671 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05001672 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001673 client_conn.set_connect_state()
1674 return client_conn
1675
1676
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001677 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001678 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001679 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001680 reading from the output of each and writing those bytes to the input of
1681 the other and in this way establish a connection and exchange
1682 application-level bytes with each other.
1683 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001684 server_conn = self._server(None)
1685 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05001686
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001687 # There should be no key or nonces yet.
1688 self.assertIdentical(server_conn.master_key(), None)
1689 self.assertIdentical(server_conn.client_random(), None)
1690 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05001691
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001692 # First, the handshake needs to happen. We'll deliver bytes back and
1693 # forth between the client and server until neither of them feels like
1694 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001695 self.assertIdentical(
1696 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001697
1698 # Now that the handshake is done, there should be a key and nonces.
1699 self.assertNotIdentical(server_conn.master_key(), None)
1700 self.assertNotIdentical(server_conn.client_random(), None)
1701 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04001702 self.assertEquals(server_conn.client_random(), client_conn.client_random())
1703 self.assertEquals(server_conn.server_random(), client_conn.server_random())
1704 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
1705 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001706
1707 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04001708 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05001709
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001710 server_conn.write(important_message)
1711 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001712 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001713 (client_conn, important_message))
1714
1715 client_conn.write(important_message[::-1])
1716 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001717 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001718 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05001719
1720
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001721 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05001722 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001723 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001724
1725 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09001726 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001727 this test fails, there must be a problem outside the memory BIO
1728 code, as no memory BIO is involved here). Even though this isn't a
1729 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05001730 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04001731 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05001732
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04001733 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05001734 client_conn.send(important_message)
1735 msg = server_conn.recv(1024)
1736 self.assertEqual(msg, important_message)
1737
1738 # Again in the other direction, just for fun.
1739 important_message = important_message[::-1]
1740 server_conn.send(important_message)
1741 msg = client_conn.recv(1024)
1742 self.assertEqual(msg, important_message)
1743
1744
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04001745 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05001746 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001747 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
1748 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05001749 """
1750 context = Context(SSLv3_METHOD)
1751 client = socket()
1752 clientSSL = Connection(context, client)
1753 self.assertRaises( TypeError, clientSSL.bio_read, 100)
1754 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04001755 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001756
1757
1758 def test_outgoingOverflow(self):
1759 """
1760 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001761 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001762 returned and that many bytes from the beginning of the input can be
1763 read from the other end of the connection.
1764 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001765 server = self._server(None)
1766 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001767
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001768 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001769
1770 size = 2 ** 15
1771 sent = client.send("x" * size)
1772 # Sanity check. We're trying to test what happens when the entire
1773 # input can't be sent. If the entire input was sent, this test is
1774 # meaningless.
1775 self.assertTrue(sent < size)
1776
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001777 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001778 self.assertIdentical(receiver, server)
1779
1780 # We can rely on all of these bytes being received at once because
1781 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
1782 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04001783
1784
1785 def test_shutdown(self):
1786 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001787 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
1788 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04001789 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001790 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04001791 server.bio_shutdown()
1792 e = self.assertRaises(Error, server.recv, 1024)
1793 # We don't want WantReadError or ZeroReturnError or anything - it's a
1794 # handshake failure.
1795 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04001796
1797
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001798 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001799 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001800 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 -04001801
Jonathan Ballet78b92a22011-07-16 08:07:26 +09001802 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001803 before the client and server are connected to each other. This
1804 function should specify a list of CAs for the server to send to the
1805 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09001806 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001807 times.
1808 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001809 server = self._server(None)
1810 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001811 self.assertEqual(client.get_client_ca_list(), [])
1812 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001813 ctx = server.get_context()
1814 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001815 self.assertEqual(client.get_client_ca_list(), [])
1816 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001817 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001818 self.assertEqual(client.get_client_ca_list(), expected)
1819 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001820
1821
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001822 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001823 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001824 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001825 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001826 """
1827 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001828 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
1829 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
1830 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001831
1832
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001833 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001834 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001835 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001836 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09001837 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001838 after the connection is set up.
1839 """
1840 def no_ca(ctx):
1841 ctx.set_client_ca_list([])
1842 return []
1843 self._check_client_ca_list(no_ca)
1844
1845
1846 def test_set_one_ca_list(self):
1847 """
1848 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001849 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001850 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001851 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001852 X509Name after the connection is set up.
1853 """
1854 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1855 cadesc = cacert.get_subject()
1856 def single_ca(ctx):
1857 ctx.set_client_ca_list([cadesc])
1858 return [cadesc]
1859 self._check_client_ca_list(single_ca)
1860
1861
1862 def test_set_multiple_ca_list(self):
1863 """
1864 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001865 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001866 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001867 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001868 X509Names after the connection is set up.
1869 """
1870 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1871 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1872
1873 sedesc = secert.get_subject()
1874 cldesc = clcert.get_subject()
1875
1876 def multiple_ca(ctx):
1877 L = [sedesc, cldesc]
1878 ctx.set_client_ca_list(L)
1879 return L
1880 self._check_client_ca_list(multiple_ca)
1881
1882
1883 def test_reset_ca_list(self):
1884 """
1885 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09001886 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001887 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001888 """
1889 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1890 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1891 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1892
1893 cadesc = cacert.get_subject()
1894 sedesc = secert.get_subject()
1895 cldesc = clcert.get_subject()
1896
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001897 def changed_ca(ctx):
1898 ctx.set_client_ca_list([sedesc, cldesc])
1899 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001900 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001901 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001902
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001903
1904 def test_mutated_ca_list(self):
1905 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001906 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001907 afterwards, this does not affect the list of CA names sent to the
1908 client.
1909 """
1910 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1911 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1912
1913 cadesc = cacert.get_subject()
1914 sedesc = secert.get_subject()
1915
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001916 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001917 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001918 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001919 L.append(sedesc)
1920 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001921 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001922
1923
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001924 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001925 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001926 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001927 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001928 """
1929 ctx = Context(TLSv1_METHOD)
1930 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001931 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001932 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001933 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001934
1935
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001936 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001937 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001938 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09001939 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001940 """
1941 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1942 cadesc = cacert.get_subject()
1943 def single_ca(ctx):
1944 ctx.add_client_ca(cacert)
1945 return [cadesc]
1946 self._check_client_ca_list(single_ca)
1947
1948
1949 def test_multiple_add_client_ca(self):
1950 """
1951 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09001952 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001953 """
1954 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1955 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1956
1957 cadesc = cacert.get_subject()
1958 sedesc = secert.get_subject()
1959
1960 def multiple_ca(ctx):
1961 ctx.add_client_ca(cacert)
1962 ctx.add_client_ca(secert)
1963 return [cadesc, sedesc]
1964 self._check_client_ca_list(multiple_ca)
1965
1966
1967 def test_set_and_add_client_ca(self):
1968 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001969 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
1970 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001971 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001972 """
1973 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1974 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1975 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1976
1977 cadesc = cacert.get_subject()
1978 sedesc = secert.get_subject()
1979 cldesc = clcert.get_subject()
1980
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001981 def mixed_set_add_ca(ctx):
1982 ctx.set_client_ca_list([cadesc, sedesc])
1983 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001984 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001985 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001986
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001987
1988 def test_set_after_add_client_ca(self):
1989 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001990 A call to :py:obj:`Context.set_client_ca_list` after a call to
1991 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001992 call with the names specified by the latter cal.
1993 """
1994 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1995 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1996 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1997
1998 cadesc = cacert.get_subject()
1999 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002000
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002001 def set_replaces_add_ca(ctx):
2002 ctx.add_client_ca(clcert)
2003 ctx.set_client_ca_list([cadesc])
2004 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002005 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002006 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002007
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002008
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04002009class InfoConstantTests(TestCase):
2010 """
2011 Tests for assorted constants exposed for use in info callbacks.
2012 """
2013 def test_integers(self):
2014 """
2015 All of the info constants are integers.
2016
2017 This is a very weak test. It would be nice to have one that actually
2018 verifies that as certain info events happen, the value passed to the
2019 info callback matches up with the constant exposed by OpenSSL.SSL.
2020 """
2021 for const in [
2022 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
2023 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
2024 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
2025 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
2026 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
2027 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
2028
2029 self.assertTrue(isinstance(const, int))
2030
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02002031
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002032if __name__ == '__main__':
2033 main()