blob: cda6d53a0463ac6b6c4015d1186bc82574269f5d [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 Calderone313bf012012-02-08 13:02:49 -050013from os.path import join, dirname
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 (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050031 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
32 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
33 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
34
35from OpenSSL.SSL import (
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040036 Error, SysCallError, WantReadError, ZeroReturnError, SSLeay_version)
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040037from OpenSSL.SSL import Context, ContextType, Connection, ConnectionType
38
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -040039from OpenSSL.test.util import TestCase, bytes, b
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040040from OpenSSL.test.test_crypto import (
41 cleartextCertificatePEM, cleartextPrivateKeyPEM)
42from OpenSSL.test.test_crypto import (
43 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
44 root_cert_pem)
45
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050046try:
47 from OpenSSL.SSL import OP_NO_QUERY_MTU
48except ImportError:
49 OP_NO_QUERY_MTU = None
50try:
51 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
52except ImportError:
53 OP_COOKIE_EXCHANGE = None
54try:
55 from OpenSSL.SSL import OP_NO_TICKET
56except ImportError:
57 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040058
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040059try:
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -040060 from OpenSSL.SSL import OP_NO_COMPRESSION
61except ImportError:
62 OP_NO_COMPRESSION = None
63
64try:
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040065 from OpenSSL.SSL import MODE_RELEASE_BUFFERS
66except ImportError:
67 MODE_RELEASE_BUFFERS = None
68
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040069from OpenSSL.SSL import (
70 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
71 SSL_ST_OK, SSL_ST_RENEGOTIATE,
72 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
73 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
74 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
75 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040076
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040077# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
78# to use)
79dhparam = """\
80-----BEGIN DH PARAMETERS-----
81MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
82-----END DH PARAMETERS-----
83"""
84
85
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040086def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040087 return ok
88
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040089
Rick Deanb1ccd562009-07-09 23:52:39 -050090def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040091 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -040092 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040093 """
94 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -050095 port = socket()
96 port.bind(('', 0))
97 port.listen(1)
98 client = socket()
99 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400100 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400101 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500102 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500103
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400104 # Let's pass some unencrypted data to make sure our socket connection is
105 # fine. Just one byte, so we don't have to worry about buffers getting
106 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400107 server.send(b("x"))
108 assert client.recv(1024) == b("x")
109 client.send(b("y"))
110 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500111
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400112 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400113 server.setblocking(False)
114 client.setblocking(False)
115
Rick Deanb1ccd562009-07-09 23:52:39 -0500116 return (server, client)
117
118
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400119
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400120def handshake(client, server):
121 conns = [client, server]
122 while conns:
123 for conn in conns:
124 try:
125 conn.do_handshake()
126 except WantReadError:
127 pass
128 else:
129 conns.remove(conn)
130
131
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400132def _create_certificate_chain():
133 """
134 Construct and return a chain of certificates.
135
136 1. A new self-signed certificate authority certificate (cacert)
137 2. A new intermediate certificate signed by cacert (icert)
138 3. A new server certificate signed by icert (scert)
139 """
140 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
141
142 # Step 1
143 cakey = PKey()
144 cakey.generate_key(TYPE_RSA, 512)
145 cacert = X509()
146 cacert.get_subject().commonName = "Authority Certificate"
147 cacert.set_issuer(cacert.get_subject())
148 cacert.set_pubkey(cakey)
149 cacert.set_notBefore(b("20000101000000Z"))
150 cacert.set_notAfter(b("20200101000000Z"))
151 cacert.add_extensions([caext])
152 cacert.set_serial_number(0)
153 cacert.sign(cakey, "sha1")
154
155 # Step 2
156 ikey = PKey()
157 ikey.generate_key(TYPE_RSA, 512)
158 icert = X509()
159 icert.get_subject().commonName = "Intermediate Certificate"
160 icert.set_issuer(cacert.get_subject())
161 icert.set_pubkey(ikey)
162 icert.set_notBefore(b("20000101000000Z"))
163 icert.set_notAfter(b("20200101000000Z"))
164 icert.add_extensions([caext])
165 icert.set_serial_number(0)
166 icert.sign(cakey, "sha1")
167
168 # Step 3
169 skey = PKey()
170 skey.generate_key(TYPE_RSA, 512)
171 scert = X509()
172 scert.get_subject().commonName = "Server Certificate"
173 scert.set_issuer(icert.get_subject())
174 scert.set_pubkey(skey)
175 scert.set_notBefore(b("20000101000000Z"))
176 scert.set_notAfter(b("20200101000000Z"))
177 scert.add_extensions([
178 X509Extension(b('basicConstraints'), True, b('CA:false'))])
179 scert.set_serial_number(0)
180 scert.sign(ikey, "sha1")
181
182 return [(cakey, cacert), (ikey, icert), (skey, scert)]
183
184
185
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400186class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400187 """
188 Helper mixin which defines methods for creating a connected socket pair and
189 for forcing two connected SSL sockets to talk to each other via memory BIOs.
190 """
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400191 def _loopback(self):
192 (server, client) = socket_pair()
193
194 ctx = Context(TLSv1_METHOD)
195 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
196 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
197 server = Connection(ctx, server)
198 server.set_accept_state()
199 client = Connection(Context(TLSv1_METHOD), client)
200 client.set_connect_state()
201
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400202 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400203
204 server.setblocking(True)
205 client.setblocking(True)
206 return server, client
207
208
209 def _interactInMemory(self, client_conn, server_conn):
210 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900211 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400212 objects. Copy bytes back and forth between their send/receive buffers
213 for as long as there is anything to copy. When there is nothing more
Jonathan Ballet648875f2011-07-16 14:14:58 +0900214 to copy, return :py:obj:`None`. If one of them actually manages to deliver
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400215 some application bytes, return a two-tuple of the connection from which
216 the bytes were read and the bytes themselves.
217 """
218 wrote = True
219 while wrote:
220 # Loop until neither side has anything to say
221 wrote = False
222
223 # Copy stuff from each side's send buffer to the other side's
224 # receive buffer.
225 for (read, write) in [(client_conn, server_conn),
226 (server_conn, client_conn)]:
227
228 # Give the side a chance to generate some more bytes, or
229 # succeed.
230 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400231 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400232 except WantReadError:
233 # It didn't succeed, so we'll hope it generated some
234 # output.
235 pass
236 else:
237 # It did succeed, so we'll stop now and let the caller deal
238 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400239 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400240
241 while True:
242 # Keep copying as long as there's more stuff there.
243 try:
244 dirty = read.bio_read(4096)
245 except WantReadError:
246 # Okay, nothing more waiting to be sent. Stop
247 # processing this send buffer.
248 break
249 else:
250 # Keep track of the fact that someone generated some
251 # output.
252 wrote = True
253 write.bio_write(dirty)
254
255
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400256
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400257class VersionTests(TestCase):
258 """
259 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900260 :py:obj:`OpenSSL.SSL.SSLeay_version` and
261 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400262 """
263 def test_OPENSSL_VERSION_NUMBER(self):
264 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900265 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400266 byte and the patch, fix, minor, and major versions in the
267 nibbles above that.
268 """
269 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
270
271
272 def test_SSLeay_version(self):
273 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900274 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400275 one of a number of version strings based on that indicator.
276 """
277 versions = {}
278 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
279 SSLEAY_PLATFORM, SSLEAY_DIR]:
280 version = SSLeay_version(t)
281 versions[version] = t
282 self.assertTrue(isinstance(version, bytes))
283 self.assertEqual(len(versions), 5)
284
285
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400286
287class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400288 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900289 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400290 """
291 def test_method(self):
292 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900293 :py:obj:`Context` can be instantiated with one of :py:obj:`SSLv2_METHOD`,
294 :py:obj:`SSLv3_METHOD`, :py:obj:`SSLv23_METHOD`, or :py:obj:`TLSv1_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400295 """
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400296 for meth in [SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400297 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400298
299 try:
300 Context(SSLv2_METHOD)
301 except ValueError:
302 # Some versions of OpenSSL have SSLv2, some don't.
303 # Difficult to say in advance.
304 pass
305
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400306 self.assertRaises(TypeError, Context, "")
307 self.assertRaises(ValueError, Context, 10)
308
309
Rick Deane15b1472009-07-09 15:53:42 -0500310 def test_type(self):
311 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900312 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400313 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500314 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400315 self.assertIdentical(Context, ContextType)
316 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500317
318
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400319 def test_use_privatekey(self):
320 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900321 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400322 """
323 key = PKey()
324 key.generate_key(TYPE_RSA, 128)
325 ctx = Context(TLSv1_METHOD)
326 ctx.use_privatekey(key)
327 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400328
329
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400330 def test_set_app_data_wrong_args(self):
331 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900332 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called with other than
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400333 one argument.
334 """
335 context = Context(TLSv1_METHOD)
336 self.assertRaises(TypeError, context.set_app_data)
337 self.assertRaises(TypeError, context.set_app_data, None, None)
338
339
340 def test_get_app_data_wrong_args(self):
341 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900342 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400343 arguments.
344 """
345 context = Context(TLSv1_METHOD)
346 self.assertRaises(TypeError, context.get_app_data, None)
347
348
349 def test_app_data(self):
350 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900351 :py:obj:`Context.set_app_data` stores an object for later retrieval using
352 :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400353 """
354 app_data = object()
355 context = Context(TLSv1_METHOD)
356 context.set_app_data(app_data)
357 self.assertIdentical(context.get_app_data(), app_data)
358
359
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400360 def test_set_options_wrong_args(self):
361 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900362 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with the wrong
363 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400364 """
365 context = Context(TLSv1_METHOD)
366 self.assertRaises(TypeError, context.set_options)
367 self.assertRaises(TypeError, context.set_options, None)
368 self.assertRaises(TypeError, context.set_options, 1, None)
369
370
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300371 def test_set_mode_wrong_args(self):
372 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400373 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with the wrong
374 number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300375 """
376 context = Context(TLSv1_METHOD)
377 self.assertRaises(TypeError, context.set_mode)
378 self.assertRaises(TypeError, context.set_mode, None)
379 self.assertRaises(TypeError, context.set_mode, 1, None)
380
381
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400382 if MODE_RELEASE_BUFFERS is not None:
383 def test_set_mode(self):
384 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400385 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the newly
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400386 set mode.
387 """
388 context = Context(TLSv1_METHOD)
389 self.assertTrue(
390 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
391 else:
392 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
393
394
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400395 def test_set_timeout_wrong_args(self):
396 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900397 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with the wrong
398 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400399 """
400 context = Context(TLSv1_METHOD)
401 self.assertRaises(TypeError, context.set_timeout)
402 self.assertRaises(TypeError, context.set_timeout, None)
403 self.assertRaises(TypeError, context.set_timeout, 1, None)
404
405
406 def test_get_timeout_wrong_args(self):
407 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900408 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400409 """
410 context = Context(TLSv1_METHOD)
411 self.assertRaises(TypeError, context.get_timeout, None)
412
413
414 def test_timeout(self):
415 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900416 :py:obj:`Context.set_timeout` sets the session timeout for all connections
417 created using the context object. :py:obj:`Context.get_timeout` retrieves this
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400418 value.
419 """
420 context = Context(TLSv1_METHOD)
421 context.set_timeout(1234)
422 self.assertEquals(context.get_timeout(), 1234)
423
424
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400425 def test_set_verify_depth_wrong_args(self):
426 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900427 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called with the wrong
428 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400429 """
430 context = Context(TLSv1_METHOD)
431 self.assertRaises(TypeError, context.set_verify_depth)
432 self.assertRaises(TypeError, context.set_verify_depth, None)
433 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
434
435
436 def test_get_verify_depth_wrong_args(self):
437 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900438 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400439 """
440 context = Context(TLSv1_METHOD)
441 self.assertRaises(TypeError, context.get_verify_depth, None)
442
443
444 def test_verify_depth(self):
445 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900446 :py:obj:`Context.set_verify_depth` sets the number of certificates in a chain
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400447 to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900448 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400449 """
450 context = Context(TLSv1_METHOD)
451 context.set_verify_depth(11)
452 self.assertEquals(context.get_verify_depth(), 11)
453
454
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400455 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400456 """
457 Write a new private key out to a new file, encrypted using the given
458 passphrase. Return the path to the new file.
459 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400460 key = PKey()
461 key.generate_key(TYPE_RSA, 128)
462 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400463 fObj = open(pemFile, 'w')
464 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
465 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400466 fObj.close()
467 return pemFile
468
469
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400470 def test_set_passwd_cb_wrong_args(self):
471 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900472 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called with the
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400473 wrong arguments or with a non-callable first argument.
474 """
475 context = Context(TLSv1_METHOD)
476 self.assertRaises(TypeError, context.set_passwd_cb)
477 self.assertRaises(TypeError, context.set_passwd_cb, None)
478 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
479
480
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400481 def test_set_passwd_cb(self):
482 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900483 :py:obj:`Context.set_passwd_cb` accepts a callable which will be invoked when
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400484 a private key is loaded from an encrypted PEM.
485 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400486 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400487 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400488 calledWith = []
489 def passphraseCallback(maxlen, verify, extra):
490 calledWith.append((maxlen, verify, extra))
491 return passphrase
492 context = Context(TLSv1_METHOD)
493 context.set_passwd_cb(passphraseCallback)
494 context.use_privatekey_file(pemFile)
495 self.assertTrue(len(calledWith), 1)
496 self.assertTrue(isinstance(calledWith[0][0], int))
497 self.assertTrue(isinstance(calledWith[0][1], int))
498 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400499
500
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400501 def test_passwd_callback_exception(self):
502 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900503 :py:obj:`Context.use_privatekey_file` propagates any exception raised by the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400504 passphrase callback.
505 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400506 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400507 def passphraseCallback(maxlen, verify, extra):
508 raise RuntimeError("Sorry, I am a fail.")
509
510 context = Context(TLSv1_METHOD)
511 context.set_passwd_cb(passphraseCallback)
512 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
513
514
515 def test_passwd_callback_false(self):
516 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900517 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400518 passphrase callback returns a false value.
519 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400520 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400521 def passphraseCallback(maxlen, verify, extra):
522 return None
523
524 context = Context(TLSv1_METHOD)
525 context.set_passwd_cb(passphraseCallback)
526 self.assertRaises(Error, context.use_privatekey_file, pemFile)
527
528
529 def test_passwd_callback_non_string(self):
530 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900531 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400532 passphrase callback returns a true non-string value.
533 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400534 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400535 def passphraseCallback(maxlen, verify, extra):
536 return 10
537
538 context = Context(TLSv1_METHOD)
539 context.set_passwd_cb(passphraseCallback)
540 self.assertRaises(Error, context.use_privatekey_file, pemFile)
541
542
543 def test_passwd_callback_too_long(self):
544 """
545 If the passphrase returned by the passphrase callback returns a string
546 longer than the indicated maximum length, it is truncated.
547 """
548 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400549 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400550 pemFile = self._write_encrypted_pem(passphrase)
551 def passphraseCallback(maxlen, verify, extra):
552 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400553 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400554
555 context = Context(TLSv1_METHOD)
556 context.set_passwd_cb(passphraseCallback)
557 # This shall succeed because the truncated result is the correct
558 # passphrase.
559 context.use_privatekey_file(pemFile)
560
561
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400562 def test_set_info_callback(self):
563 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900564 :py:obj:`Context.set_info_callback` accepts a callable which will be invoked
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400565 when certain information about an SSL connection is available.
566 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500567 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400568
569 clientSSL = Connection(Context(TLSv1_METHOD), client)
570 clientSSL.set_connect_state()
571
572 called = []
573 def info(conn, where, ret):
574 called.append((conn, where, ret))
575 context = Context(TLSv1_METHOD)
576 context.set_info_callback(info)
577 context.use_certificate(
578 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
579 context.use_privatekey(
580 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
581
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400582 serverSSL = Connection(context, server)
583 serverSSL.set_accept_state()
584
585 while not called:
586 for ssl in clientSSL, serverSSL:
587 try:
588 ssl.do_handshake()
589 except WantReadError:
590 pass
591
592 # Kind of lame. Just make sure it got called somehow.
593 self.assertTrue(called)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400594
595
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400596 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400597 """
598 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400599 its :py:obj:`load_verify_locations` method with the given arguments.
600 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400601 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500602 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400603
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400604 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400605 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400606 # Require that the server certificate verify properly or the
607 # connection will fail.
608 clientContext.set_verify(
609 VERIFY_PEER,
610 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
611
612 clientSSL = Connection(clientContext, client)
613 clientSSL.set_connect_state()
614
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400615 serverContext = Context(TLSv1_METHOD)
616 serverContext.use_certificate(
617 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
618 serverContext.use_privatekey(
619 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
620
621 serverSSL = Connection(serverContext, server)
622 serverSSL.set_accept_state()
623
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400624 # Without load_verify_locations above, the handshake
625 # will fail:
626 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
627 # 'certificate verify failed')]
628 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400629
630 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400631 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400632
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500633
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400634 def test_load_verify_file(self):
635 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900636 :py:obj:`Context.load_verify_locations` accepts a file name and uses the
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400637 certificates within for verification purposes.
638 """
639 cafile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400640 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400641 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400642 fObj.close()
643
644 self._load_verify_locations_test(cafile)
645
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400646
647 def test_load_verify_invalid_file(self):
648 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900649 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when passed a
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400650 non-existent cafile.
651 """
652 clientContext = Context(TLSv1_METHOD)
653 self.assertRaises(
654 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400655
656
657 def test_load_verify_directory(self):
658 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900659 :py:obj:`Context.load_verify_locations` accepts a directory name and uses
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400660 the certificates within for verification purposes.
661 """
662 capath = self.mktemp()
663 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400664 # Hash values computed manually with c_rehash to avoid depending on
665 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
666 # from OpenSSL 1.0.0.
667 for name in ['c7adac82.0', 'c3705638.0']:
668 cafile = join(capath, name)
669 fObj = open(cafile, 'w')
670 fObj.write(cleartextCertificatePEM.decode('ascii'))
671 fObj.close()
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400672
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400673 self._load_verify_locations_test(None, capath)
674
675
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400676 def test_load_verify_locations_wrong_args(self):
677 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900678 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if called with
679 the wrong number of arguments or with non-:py:obj:`str` arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400680 """
681 context = Context(TLSv1_METHOD)
682 self.assertRaises(TypeError, context.load_verify_locations)
683 self.assertRaises(TypeError, context.load_verify_locations, object())
684 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
685 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
686
687
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400688 if platform == "win32":
689 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400690 "See LP#404343 and LP#404344."
691 else:
692 def test_set_default_verify_paths(self):
693 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900694 :py:obj:`Context.set_default_verify_paths` causes the platform-specific CA
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400695 certificate locations to be used for verification purposes.
696 """
697 # Testing this requires a server with a certificate signed by one of
698 # the CAs in the platform CA location. Getting one of those costs
699 # money. Fortunately (or unfortunately, depending on your
700 # perspective), it's easy to think of a public server on the
701 # internet which has such a certificate. Connecting to the network
702 # in a unit test is bad, but it's the only way I can think of to
703 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400704
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400705 # Arg, verisign.com doesn't speak TLSv1
706 context = Context(SSLv3_METHOD)
707 context.set_default_verify_paths()
708 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +0200709 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400710 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400711
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400712 client = socket()
713 client.connect(('verisign.com', 443))
714 clientSSL = Connection(context, client)
715 clientSSL.set_connect_state()
716 clientSSL.do_handshake()
717 clientSSL.send('GET / HTTP/1.0\r\n\r\n')
718 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400719
720
721 def test_set_default_verify_paths_signature(self):
722 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900723 :py:obj:`Context.set_default_verify_paths` takes no arguments and raises
724 :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400725 """
726 context = Context(TLSv1_METHOD)
727 self.assertRaises(TypeError, context.set_default_verify_paths, None)
728 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
729 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500730
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400731
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500732 def test_add_extra_chain_cert_invalid_cert(self):
733 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900734 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if called with
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500735 other than one argument or if called with an object which is not an
Jonathan Ballet648875f2011-07-16 14:14:58 +0900736 instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500737 """
738 context = Context(TLSv1_METHOD)
739 self.assertRaises(TypeError, context.add_extra_chain_cert)
740 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
741 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
742
743
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400744 def _handshake_test(self, serverContext, clientContext):
745 """
746 Verify that a client and server created with the given contexts can
747 successfully handshake and communicate.
748 """
749 serverSocket, clientSocket = socket_pair()
750
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400751 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400752 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400753
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400754 client = Connection(clientContext, clientSocket)
755 client.set_connect_state()
756
757 # Make them talk to each other.
758 # self._interactInMemory(client, server)
759 for i in range(3):
760 for s in [client, server]:
761 try:
762 s.do_handshake()
763 except WantReadError:
764 pass
765
766
767 def test_add_extra_chain_cert(self):
768 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900769 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509` instance to add to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400770 the certificate chain.
771
Jonathan Ballet648875f2011-07-16 14:14:58 +0900772 See :py:obj:`_create_certificate_chain` for the details of the certificate
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400773 chain tested.
774
775 The chain is tested by starting a server with scert and connecting
776 to it with a client which trusts cacert and requires verification to
777 succeed.
778 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400779 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400780 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
781
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400782 # Dump the CA certificate to a file because that's the only way to load
783 # it as a trusted CA in the client context.
784 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
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_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400787 fObj.close()
788
789 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400790 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400791 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400792 fObj.close()
793
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400794 # Create the server context
795 serverContext = Context(TLSv1_METHOD)
796 serverContext.use_privatekey(skey)
797 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400798 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400799 serverContext.add_extra_chain_cert(icert)
800
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400801 # Create the client
802 clientContext = Context(TLSv1_METHOD)
803 clientContext.set_verify(
804 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
805 clientContext.load_verify_locations('ca.pem')
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400806
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400807 # Try it out.
808 self._handshake_test(serverContext, clientContext)
809
810
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400811 def test_use_certificate_chain_file(self):
812 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900813 :py:obj:`Context.use_certificate_chain_file` reads a certificate chain from
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400814 the specified file.
815
816 The chain is tested by starting a server with scert and connecting
817 to it with a client which trusts cacert and requires verification to
818 succeed.
819 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400820 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400821 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
822
823 # Write out the chain file.
824 chainFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400825 fObj = open(chainFile, 'w')
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400826 # Most specific to least general.
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400827 fObj.write(dump_certificate(FILETYPE_PEM, scert).decode('ascii'))
828 fObj.write(dump_certificate(FILETYPE_PEM, icert).decode('ascii'))
829 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400830 fObj.close()
831
832 serverContext = Context(TLSv1_METHOD)
833 serverContext.use_certificate_chain_file(chainFile)
834 serverContext.use_privatekey(skey)
835
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400836 fObj = open('ca.pem', 'w')
837 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400838 fObj.close()
839
840 clientContext = Context(TLSv1_METHOD)
841 clientContext.set_verify(
842 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
843 clientContext.load_verify_locations('ca.pem')
844
845 self._handshake_test(serverContext, clientContext)
846
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -0400847 # XXX load_client_ca
848 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -0400849
850 def test_get_verify_mode_wrong_args(self):
851 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900852 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -0400853 arguments.
854 """
855 context = Context(TLSv1_METHOD)
856 self.assertRaises(TypeError, context.get_verify_mode, None)
857
858
859 def test_get_verify_mode(self):
860 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900861 :py:obj:`Context.get_verify_mode` returns the verify mode flags previously
862 passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -0400863 """
864 context = Context(TLSv1_METHOD)
865 self.assertEquals(context.get_verify_mode(), 0)
866 context.set_verify(
867 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
868 self.assertEquals(
869 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
870
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400871
872 def test_load_tmp_dh_wrong_args(self):
873 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900874 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
875 number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400876 """
877 context = Context(TLSv1_METHOD)
878 self.assertRaises(TypeError, context.load_tmp_dh)
879 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
880 self.assertRaises(TypeError, context.load_tmp_dh, object())
881
882
883 def test_load_tmp_dh_missing_file(self):
884 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900885 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the specified file
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400886 does not exist.
887 """
888 context = Context(TLSv1_METHOD)
889 self.assertRaises(Error, context.load_tmp_dh, "hello")
890
891
892 def test_load_tmp_dh(self):
893 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900894 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400895 specified file.
896 """
897 context = Context(TLSv1_METHOD)
898 dhfilename = self.mktemp()
899 dhfile = open(dhfilename, "w")
900 dhfile.write(dhparam)
901 dhfile.close()
902 context.load_tmp_dh(dhfilename)
903 # XXX What should I assert here? -exarkun
904
905
906 def test_set_cipher_list(self):
907 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900908 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`str` naming the ciphers which
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400909 connections created with the context object will be able to choose from.
910 """
911 context = Context(TLSv1_METHOD)
912 context.set_cipher_list("hello world:EXP-RC4-MD5")
913 conn = Connection(context, None)
914 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400915
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400916
Jean-Paul Calderone313bf012012-02-08 13:02:49 -0500917 def test_set_session_cache_mode_wrong_args(self):
918 """
919 L{Context.set_session_cache_mode} raises L{TypeError} if called with
920 other than one integer argument.
921 """
922 context = Context(TLSv1_METHOD)
923 self.assertRaises(TypeError, context.set_session_cache_mode)
924 self.assertRaises(TypeError, context.set_session_cache_mode, object())
925
926
927 def test_get_session_cache_mode_wrong_args(self):
928 """
929 L{Context.get_session_cache_mode} raises L{TypeError} if called with any
930 arguments.
931 """
932 context = Context(TLSv1_METHOD)
933 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
934
935
936 def test_session_cache_mode(self):
937 """
938 L{Context.set_session_cache_mode} specifies how sessions are cached.
939 The setting can be retrieved via L{Context.get_session_cache_mode}.
940 """
941 context = Context(TLSv1_METHOD)
942 old = context.set_session_cache_mode(SESS_CACHE_OFF)
943 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
944 self.assertEqual(SESS_CACHE_OFF, off)
945 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
946
947
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400948
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -0400949class ServerNameCallbackTests(TestCase, _LoopbackMixin):
950 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900951 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
952 :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -0400953 """
954 def test_wrong_args(self):
955 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900956 :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -0400957 with other than one argument.
958 """
959 context = Context(TLSv1_METHOD)
960 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
961 self.assertRaises(
962 TypeError, context.set_tlsext_servername_callback, 1, 2)
963
964 def test_old_callback_forgotten(self):
965 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900966 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -0400967 callback, the one it replaces is dereferenced.
968 """
969 def callback(connection):
970 pass
971
972 def replacement(connection):
973 pass
974
975 context = Context(TLSv1_METHOD)
976 context.set_tlsext_servername_callback(callback)
977
978 tracker = ref(callback)
979 del callback
980
981 context.set_tlsext_servername_callback(replacement)
982 collect()
983 self.assertIdentical(None, tracker())
984
985
986 def test_no_servername(self):
987 """
988 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +0900989 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
990 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -0400991 """
992 args = []
993 def servername(conn):
994 args.append((conn, conn.get_servername()))
995 context = Context(TLSv1_METHOD)
996 context.set_tlsext_servername_callback(servername)
997
998 # Lose our reference to it. The Context is responsible for keeping it
999 # alive now.
1000 del servername
1001 collect()
1002
1003 # Necessary to actually accept the connection
1004 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1005 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1006
1007 # Do a little connection to trigger the logic
1008 server = Connection(context, None)
1009 server.set_accept_state()
1010
1011 client = Connection(Context(TLSv1_METHOD), None)
1012 client.set_connect_state()
1013
1014 self._interactInMemory(server, client)
1015
1016 self.assertEqual([(server, None)], args)
1017
1018
1019 def test_servername(self):
1020 """
1021 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +09001022 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
1023 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001024 """
1025 args = []
1026 def servername(conn):
1027 args.append((conn, conn.get_servername()))
1028 context = Context(TLSv1_METHOD)
1029 context.set_tlsext_servername_callback(servername)
1030
1031 # Necessary to actually accept the connection
1032 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1033 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1034
1035 # Do a little connection to trigger the logic
1036 server = Connection(context, None)
1037 server.set_accept_state()
1038
1039 client = Connection(Context(TLSv1_METHOD), None)
1040 client.set_connect_state()
1041 client.set_tlsext_host_name(b("foo1.example.com"))
1042
1043 self._interactInMemory(server, client)
1044
1045 self.assertEqual([(server, b("foo1.example.com"))], args)
1046
1047
1048
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001049class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05001050 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001051 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001052 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001053 # XXX want_write
1054 # XXX want_read
1055 # XXX get_peer_certificate -> None
1056 # XXX sock_shutdown
1057 # XXX master_key -> TypeError
1058 # XXX server_random -> TypeError
1059 # XXX state_string
1060 # XXX connect -> TypeError
1061 # XXX connect_ex -> TypeError
1062 # XXX set_connect_state -> TypeError
1063 # XXX set_accept_state -> TypeError
1064 # XXX renegotiate_pending
1065 # XXX do_handshake -> TypeError
1066 # XXX bio_read -> TypeError
1067 # XXX recv -> TypeError
1068 # XXX send -> TypeError
1069 # XXX bio_write -> TypeError
1070
Rick Deane15b1472009-07-09 15:53:42 -05001071 def test_type(self):
1072 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001073 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001074 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05001075 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001076 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05001077 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001078 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05001079
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001080
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001081 def test_get_context(self):
1082 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001083 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
1084 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001085 """
1086 context = Context(TLSv1_METHOD)
1087 connection = Connection(context, None)
1088 self.assertIdentical(connection.get_context(), context)
1089
1090
1091 def test_get_context_wrong_args(self):
1092 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001093 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001094 arguments.
1095 """
1096 connection = Connection(Context(TLSv1_METHOD), None)
1097 self.assertRaises(TypeError, connection.get_context, None)
1098
1099
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001100 def test_set_context_wrong_args(self):
1101 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001102 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
1103 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001104 than 1.
1105 """
1106 ctx = Context(TLSv1_METHOD)
1107 connection = Connection(ctx, None)
1108 self.assertRaises(TypeError, connection.set_context)
1109 self.assertRaises(TypeError, connection.set_context, object())
1110 self.assertRaises(TypeError, connection.set_context, "hello")
1111 self.assertRaises(TypeError, connection.set_context, 1)
1112 self.assertRaises(TypeError, connection.set_context, 1, 2)
1113 self.assertRaises(
1114 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
1115 self.assertIdentical(ctx, connection.get_context())
1116
1117
1118 def test_set_context(self):
1119 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001120 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001121 for the connection.
1122 """
1123 original = Context(SSLv23_METHOD)
1124 replacement = Context(TLSv1_METHOD)
1125 connection = Connection(original, None)
1126 connection.set_context(replacement)
1127 self.assertIdentical(replacement, connection.get_context())
1128 # Lose our references to the contexts, just in case the Connection isn't
1129 # properly managing its own contributions to their reference counts.
1130 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001131 collect()
1132
1133
1134 def test_set_tlsext_host_name_wrong_args(self):
1135 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001136 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001137 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09001138 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001139 """
1140 conn = Connection(Context(TLSv1_METHOD), None)
1141 self.assertRaises(TypeError, conn.set_tlsext_host_name)
1142 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
1143 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
1144 self.assertRaises(
1145 TypeError, conn.set_tlsext_host_name, b("with\0null"))
1146
1147 if version_info >= (3,):
1148 # On Python 3.x, don't accidentally implicitly convert from text.
1149 self.assertRaises(
1150 TypeError,
1151 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001152
1153
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001154 def test_get_servername_wrong_args(self):
1155 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001156 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001157 arguments.
1158 """
1159 connection = Connection(Context(TLSv1_METHOD), None)
1160 self.assertRaises(TypeError, connection.get_servername, object())
1161 self.assertRaises(TypeError, connection.get_servername, 1)
1162 self.assertRaises(TypeError, connection.get_servername, "hello")
1163
1164
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001165 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001166 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001167 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001168 immediate read.
1169 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001170 connection = Connection(Context(TLSv1_METHOD), None)
1171 self.assertEquals(connection.pending(), 0)
1172
1173
1174 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001175 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001176 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001177 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001178 connection = Connection(Context(TLSv1_METHOD), None)
1179 self.assertRaises(TypeError, connection.pending, None)
1180
1181
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001182 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001183 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001184 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001185 argument or with the wrong number of arguments.
1186 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001187 connection = Connection(Context(TLSv1_METHOD), socket())
1188 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001189 self.assertRaises(TypeError, connection.connect)
1190 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001191
1192
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001193 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001194 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001195 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001196 connect method raises it.
1197 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001198 client = socket()
1199 context = Context(TLSv1_METHOD)
1200 clientSSL = Connection(context, client)
1201 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04001202 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001203
1204
1205 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001206 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001207 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001208 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001209 port = socket()
1210 port.bind(('', 0))
1211 port.listen(3)
1212
1213 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001214 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
1215 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001216
1217
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001218 if platform == "darwin":
1219 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
1220 else:
1221 def test_connect_ex(self):
1222 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001223 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001224 errno instead of raising an exception.
1225 """
1226 port = socket()
1227 port.bind(('', 0))
1228 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001229
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001230 clientSSL = Connection(Context(TLSv1_METHOD), socket())
1231 clientSSL.setblocking(False)
1232 result = clientSSL.connect_ex(port.getsockname())
1233 expected = (EINPROGRESS, EWOULDBLOCK)
1234 self.assertTrue(
1235 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001236
1237
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001238 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001239 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001240 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001241 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001242 connection = Connection(Context(TLSv1_METHOD), socket())
1243 self.assertRaises(TypeError, connection.accept, None)
1244
1245
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001246 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001247 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001248 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
1249 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001250 connection originated from.
1251 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001252 ctx = Context(TLSv1_METHOD)
1253 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1254 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001255 port = socket()
1256 portSSL = Connection(ctx, port)
1257 portSSL.bind(('', 0))
1258 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001259
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001260 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001261
1262 # Calling portSSL.getsockname() here to get the server IP address sounds
1263 # great, but frequently fails on Windows.
1264 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001265
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001266 serverSSL, address = portSSL.accept()
1267
1268 self.assertTrue(isinstance(serverSSL, Connection))
1269 self.assertIdentical(serverSSL.get_context(), ctx)
1270 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001271
1272
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001273 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001274 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001275 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001276 number of arguments or with arguments other than integers.
1277 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001278 connection = Connection(Context(TLSv1_METHOD), None)
1279 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04001280 self.assertRaises(TypeError, connection.get_shutdown, None)
1281 self.assertRaises(TypeError, connection.set_shutdown)
1282 self.assertRaises(TypeError, connection.set_shutdown, None)
1283 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001284
1285
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001286 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001287 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001288 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001289 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001290 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001291 self.assertFalse(server.shutdown())
1292 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001293 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001294 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
1295 client.shutdown()
1296 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
1297 self.assertRaises(ZeroReturnError, server.recv, 1024)
1298 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001299
1300
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001301 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001302 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001303 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001304 process.
1305 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001306 connection = Connection(Context(TLSv1_METHOD), socket())
1307 connection.set_shutdown(RECEIVED_SHUTDOWN)
1308 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1309
1310
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001311 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001312 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001313 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
1314 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001315 with any arguments.
1316 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001317 conn = Connection(Context(TLSv1_METHOD), None)
1318 self.assertRaises(TypeError, conn.get_app_data, None)
1319 self.assertRaises(TypeError, conn.set_app_data)
1320 self.assertRaises(TypeError, conn.set_app_data, None, None)
1321
1322
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001323 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001324 """
1325 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001326 :py:obj:`Connection.set_app_data` and later retrieved with
1327 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001328 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001329 conn = Connection(Context(TLSv1_METHOD), None)
1330 app_data = object()
1331 conn.set_app_data(app_data)
1332 self.assertIdentical(conn.get_app_data(), app_data)
1333
1334
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001335 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001336 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001337 :py:obj:`Connection.makefile` is not implemented and calling that method raises
1338 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001339 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001340 conn = Connection(Context(TLSv1_METHOD), None)
1341 self.assertRaises(NotImplementedError, conn.makefile)
1342
1343
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001344 def test_get_peer_cert_chain_wrong_args(self):
1345 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001346 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001347 arguments.
1348 """
1349 conn = Connection(Context(TLSv1_METHOD), None)
1350 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
1351 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
1352 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
1353 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
1354
1355
1356 def test_get_peer_cert_chain(self):
1357 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001358 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001359 the connected server returned for the certification verification.
1360 """
1361 chain = _create_certificate_chain()
1362 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1363
1364 serverContext = Context(TLSv1_METHOD)
1365 serverContext.use_privatekey(skey)
1366 serverContext.use_certificate(scert)
1367 serverContext.add_extra_chain_cert(icert)
1368 serverContext.add_extra_chain_cert(cacert)
1369 server = Connection(serverContext, None)
1370 server.set_accept_state()
1371
1372 # Create the client
1373 clientContext = Context(TLSv1_METHOD)
1374 clientContext.set_verify(VERIFY_NONE, verify_cb)
1375 client = Connection(clientContext, None)
1376 client.set_connect_state()
1377
1378 self._interactInMemory(client, server)
1379
1380 chain = client.get_peer_cert_chain()
1381 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001382 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001383 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001384 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001385 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001386 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001387 "Authority Certificate", chain[2].get_subject().CN)
1388
1389
1390 def test_get_peer_cert_chain_none(self):
1391 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001392 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001393 certificate chain.
1394 """
1395 ctx = Context(TLSv1_METHOD)
1396 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1397 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1398 server = Connection(ctx, None)
1399 server.set_accept_state()
1400 client = Connection(Context(TLSv1_METHOD), None)
1401 client.set_connect_state()
1402 self._interactInMemory(client, server)
1403 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001404
1405
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001406
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001407class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001408 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001409 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001410 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04001411 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001412 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001413 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001414 arguments.
1415 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001416 connection = Connection(Context(TLSv1_METHOD), None)
1417 self.assertRaises(TypeError, connection.get_cipher_list, None)
1418
1419
1420 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001421 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001422 :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 -04001423 names of the ciphers which might be used.
1424 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001425 connection = Connection(Context(TLSv1_METHOD), None)
1426 ciphers = connection.get_cipher_list()
1427 self.assertTrue(isinstance(ciphers, list))
1428 for cipher in ciphers:
1429 self.assertTrue(isinstance(cipher, str))
1430
1431
1432
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001433class ConnectionSendTests(TestCase, _LoopbackMixin):
1434 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001435 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001436 """
1437 def test_wrong_args(self):
1438 """
1439 When called with arguments other than a single string,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001440 :py:obj:`Connection.send` raises :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001441 """
1442 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05001443 self.assertRaises(TypeError, connection.send)
1444 self.assertRaises(TypeError, connection.send, object())
1445 self.assertRaises(TypeError, connection.send, "foo", "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001446
1447
1448 def test_short_bytes(self):
1449 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001450 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001451 and returns the number of bytes sent.
1452 """
1453 server, client = self._loopback()
1454 count = server.send(b('xy'))
1455 self.assertEquals(count, 2)
1456 self.assertEquals(client.recv(2), b('xy'))
1457
1458 try:
1459 memoryview
1460 except NameError:
1461 "cannot test sending memoryview without memoryview"
1462 else:
1463 def test_short_memoryview(self):
1464 """
1465 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001466 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001467 bytes sent.
1468 """
1469 server, client = self._loopback()
1470 count = server.send(memoryview(b('xy')))
1471 self.assertEquals(count, 2)
1472 self.assertEquals(client.recv(2), b('xy'))
1473
1474
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05001475
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001476class ConnectionSendallTests(TestCase, _LoopbackMixin):
1477 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001478 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001479 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001480 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001481 """
1482 When called with arguments other than a single string,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001483 :py:obj:`Connection.sendall` raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001484 """
1485 connection = Connection(Context(TLSv1_METHOD), None)
1486 self.assertRaises(TypeError, connection.sendall)
1487 self.assertRaises(TypeError, connection.sendall, object())
1488 self.assertRaises(TypeError, connection.sendall, "foo", "bar")
1489
1490
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001491 def test_short(self):
1492 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001493 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001494 it.
1495 """
1496 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001497 server.sendall(b('x'))
1498 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001499
1500
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05001501 try:
1502 memoryview
1503 except NameError:
1504 "cannot test sending memoryview without memoryview"
1505 else:
1506 def test_short_memoryview(self):
1507 """
1508 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001509 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05001510 """
1511 server, client = self._loopback()
1512 server.sendall(memoryview(b('x')))
1513 self.assertEquals(client.recv(1), b('x'))
1514
1515
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001516 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001517 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001518 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001519 it even if this requires multiple calls of an underlying write function.
1520 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001521 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04001522 # Should be enough, underlying SSL_write should only do 16k at a time.
1523 # On Windows, after 32k of bytes the write will block (forever - because
1524 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04001525 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001526 server.sendall(message)
1527 accum = []
1528 received = 0
1529 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001530 data = client.recv(1024)
1531 accum.append(data)
1532 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04001533 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001534
1535
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001536 def test_closed(self):
1537 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001538 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001539 write error from the low level write call.
1540 """
1541 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04001542 server.sock_shutdown(2)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001543 self.assertRaises(SysCallError, server.sendall, "hello, world")
1544
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001545
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001546
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001547class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
1548 """
1549 Tests for SSL renegotiation APIs.
1550 """
1551 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001552 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001553 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001554 arguments.
1555 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001556 connection = Connection(Context(TLSv1_METHOD), None)
1557 self.assertRaises(TypeError, connection.renegotiate, None)
1558
1559
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001560 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001561 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001562 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001563 any arguments.
1564 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001565 connection = Connection(Context(TLSv1_METHOD), None)
1566 self.assertRaises(TypeError, connection.total_renegotiations, None)
1567
1568
1569 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001570 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001571 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001572 renegotiations have happened.
1573 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001574 connection = Connection(Context(TLSv1_METHOD), None)
1575 self.assertEquals(connection.total_renegotiations(), 0)
1576
1577
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001578# def test_renegotiate(self):
1579# """
1580# """
1581# server, client = self._loopback()
1582
1583# server.send("hello world")
1584# self.assertEquals(client.recv(len("hello world")), "hello world")
1585
1586# self.assertEquals(server.total_renegotiations(), 0)
1587# self.assertTrue(server.renegotiate())
1588
1589# server.setblocking(False)
1590# client.setblocking(False)
1591# while server.renegotiate_pending():
1592# client.do_handshake()
1593# server.do_handshake()
1594
1595# self.assertEquals(server.total_renegotiations(), 1)
1596
1597
1598
1599
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001600class ErrorTests(TestCase):
1601 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001602 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001603 """
1604 def test_type(self):
1605 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001606 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001607 """
1608 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05001609 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05001610
1611
1612
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001613class ConstantsTests(TestCase):
1614 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001615 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001616
1617 These are values defined by OpenSSL intended only to be used as flags to
1618 OpenSSL APIs. The only assertions it seems can be made about them is
1619 their values.
1620 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001621 # unittest.TestCase has no skip mechanism
1622 if OP_NO_QUERY_MTU is not None:
1623 def test_op_no_query_mtu(self):
1624 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001625 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001626 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001627 """
1628 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
1629 else:
1630 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001631
1632
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001633 if OP_COOKIE_EXCHANGE is not None:
1634 def test_op_cookie_exchange(self):
1635 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001636 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001637 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001638 """
1639 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
1640 else:
1641 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001642
1643
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001644 if OP_NO_TICKET is not None:
1645 def test_op_no_ticket(self):
1646 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001647 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001648 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001649 """
1650 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04001651 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001652 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05001653
1654
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04001655 if OP_NO_COMPRESSION is not None:
1656 def test_op_no_compression(self):
1657 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001658 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
1659 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04001660 """
1661 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
1662 else:
1663 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
1664
1665
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001666 def test_sess_cache_off(self):
1667 """
1668 The value of L{OpenSSL.SSL.SESS_CACHE_OFF} 0x0, the value of
1669 L{SSL_SESS_CACHE_OFF} defined by I{openssl/ssl.h}.
1670 """
1671 self.assertEqual(0x0, SESS_CACHE_OFF)
1672
1673
1674 def test_sess_cache_client(self):
1675 """
1676 The value of L{OpenSSL.SSL.SESS_CACHE_CLIENT} 0x1, the value of
1677 L{SSL_SESS_CACHE_CLIENT} defined by I{openssl/ssl.h}.
1678 """
1679 self.assertEqual(0x1, SESS_CACHE_CLIENT)
1680
1681
1682 def test_sess_cache_server(self):
1683 """
1684 The value of L{OpenSSL.SSL.SESS_CACHE_SERVER} 0x2, the value of
1685 L{SSL_SESS_CACHE_SERVER} defined by I{openssl/ssl.h}.
1686 """
1687 self.assertEqual(0x2, SESS_CACHE_SERVER)
1688
1689
1690 def test_sess_cache_both(self):
1691 """
1692 The value of L{OpenSSL.SSL.SESS_CACHE_BOTH} 0x3, the value of
1693 L{SSL_SESS_CACHE_BOTH} defined by I{openssl/ssl.h}.
1694 """
1695 self.assertEqual(0x3, SESS_CACHE_BOTH)
1696
1697
1698 def test_sess_cache_no_auto_clear(self):
1699 """
1700 The value of L{OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR} 0x80, the value of
1701 L{SSL_SESS_CACHE_NO_AUTO_CLEAR} defined by I{openssl/ssl.h}.
1702 """
1703 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
1704
1705
1706 def test_sess_cache_no_internal_lookup(self):
1707 """
1708 The value of L{OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP} 0x100, the
1709 value of L{SSL_SESS_CACHE_NO_INTERNAL_LOOKUP} defined by
1710 I{openssl/ssl.h}.
1711 """
1712 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
1713
1714
1715 def test_sess_cache_no_internal_store(self):
1716 """
1717 The value of L{OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE} 0x200, the
1718 value of L{SSL_SESS_CACHE_NO_INTERNAL_STORE} defined by
1719 I{openssl/ssl.h}.
1720 """
1721 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
1722
1723
1724 def test_sess_cache_no_internal(self):
1725 """
1726 The value of L{OpenSSL.SSL.SESS_CACHE_NO_INTERNAL} 0x300, the value of
1727 L{SSL_SESS_CACHE_NO_INTERNAL} defined by I{openssl/ssl.h}.
1728 """
1729 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
1730
1731
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04001732
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001733class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05001734 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001735 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05001736 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001737 def _server(self, sock):
1738 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001739 Create a new server-side SSL :py:obj:`Connection` object wrapped around
1740 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001741 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001742 # Create the server side Connection. This is mostly setup boilerplate
1743 # - use TLSv1, use a particular certificate, etc.
1744 server_ctx = Context(TLSv1_METHOD)
1745 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
1746 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
1747 server_store = server_ctx.get_cert_store()
1748 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1749 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1750 server_ctx.check_privatekey()
1751 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05001752 # Here the Connection is actually created. If None is passed as the 2nd
1753 # parameter, it indicates a memory BIO should be created.
1754 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001755 server_conn.set_accept_state()
1756 return server_conn
1757
1758
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001759 def _client(self, sock):
1760 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001761 Create a new client-side SSL :py:obj:`Connection` object wrapped around
1762 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001763 """
1764 # Now create the client side Connection. Similar boilerplate to the
1765 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001766 client_ctx = Context(TLSv1_METHOD)
1767 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
1768 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
1769 client_store = client_ctx.get_cert_store()
1770 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
1771 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
1772 client_ctx.check_privatekey()
1773 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05001774 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001775 client_conn.set_connect_state()
1776 return client_conn
1777
1778
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001779 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001780 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001781 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001782 reading from the output of each and writing those bytes to the input of
1783 the other and in this way establish a connection and exchange
1784 application-level bytes with each other.
1785 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001786 server_conn = self._server(None)
1787 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05001788
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001789 # There should be no key or nonces yet.
1790 self.assertIdentical(server_conn.master_key(), None)
1791 self.assertIdentical(server_conn.client_random(), None)
1792 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05001793
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001794 # First, the handshake needs to happen. We'll deliver bytes back and
1795 # forth between the client and server until neither of them feels like
1796 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001797 self.assertIdentical(
1798 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001799
1800 # Now that the handshake is done, there should be a key and nonces.
1801 self.assertNotIdentical(server_conn.master_key(), None)
1802 self.assertNotIdentical(server_conn.client_random(), None)
1803 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04001804 self.assertEquals(server_conn.client_random(), client_conn.client_random())
1805 self.assertEquals(server_conn.server_random(), client_conn.server_random())
1806 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
1807 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001808
1809 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04001810 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05001811
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001812 server_conn.write(important_message)
1813 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001814 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001815 (client_conn, important_message))
1816
1817 client_conn.write(important_message[::-1])
1818 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001819 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001820 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05001821
1822
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001823 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05001824 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001825 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001826
1827 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09001828 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001829 this test fails, there must be a problem outside the memory BIO
1830 code, as no memory BIO is involved here). Even though this isn't a
1831 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05001832 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04001833 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05001834
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04001835 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05001836 client_conn.send(important_message)
1837 msg = server_conn.recv(1024)
1838 self.assertEqual(msg, important_message)
1839
1840 # Again in the other direction, just for fun.
1841 important_message = important_message[::-1]
1842 server_conn.send(important_message)
1843 msg = client_conn.recv(1024)
1844 self.assertEqual(msg, important_message)
1845
1846
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04001847 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05001848 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001849 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
1850 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05001851 """
1852 context = Context(SSLv3_METHOD)
1853 client = socket()
1854 clientSSL = Connection(context, client)
1855 self.assertRaises( TypeError, clientSSL.bio_read, 100)
1856 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04001857 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001858
1859
1860 def test_outgoingOverflow(self):
1861 """
1862 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001863 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001864 returned and that many bytes from the beginning of the input can be
1865 read from the other end of the connection.
1866 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001867 server = self._server(None)
1868 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001869
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001870 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001871
1872 size = 2 ** 15
1873 sent = client.send("x" * size)
1874 # Sanity check. We're trying to test what happens when the entire
1875 # input can't be sent. If the entire input was sent, this test is
1876 # meaningless.
1877 self.assertTrue(sent < size)
1878
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001879 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001880 self.assertIdentical(receiver, server)
1881
1882 # We can rely on all of these bytes being received at once because
1883 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
1884 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04001885
1886
1887 def test_shutdown(self):
1888 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001889 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
1890 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04001891 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001892 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04001893 server.bio_shutdown()
1894 e = self.assertRaises(Error, server.recv, 1024)
1895 # We don't want WantReadError or ZeroReturnError or anything - it's a
1896 # handshake failure.
1897 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04001898
1899
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001900 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001901 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001902 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 -04001903
Jonathan Ballet78b92a22011-07-16 08:07:26 +09001904 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001905 before the client and server are connected to each other. This
1906 function should specify a list of CAs for the server to send to the
1907 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09001908 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001909 times.
1910 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001911 server = self._server(None)
1912 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001913 self.assertEqual(client.get_client_ca_list(), [])
1914 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001915 ctx = server.get_context()
1916 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001917 self.assertEqual(client.get_client_ca_list(), [])
1918 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001919 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001920 self.assertEqual(client.get_client_ca_list(), expected)
1921 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001922
1923
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001924 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001925 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001926 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001927 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001928 """
1929 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001930 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
1931 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
1932 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001933
1934
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001935 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001936 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001937 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001938 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09001939 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001940 after the connection is set up.
1941 """
1942 def no_ca(ctx):
1943 ctx.set_client_ca_list([])
1944 return []
1945 self._check_client_ca_list(no_ca)
1946
1947
1948 def test_set_one_ca_list(self):
1949 """
1950 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001951 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001952 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001953 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001954 X509Name after the connection is set up.
1955 """
1956 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1957 cadesc = cacert.get_subject()
1958 def single_ca(ctx):
1959 ctx.set_client_ca_list([cadesc])
1960 return [cadesc]
1961 self._check_client_ca_list(single_ca)
1962
1963
1964 def test_set_multiple_ca_list(self):
1965 """
1966 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001967 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001968 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001969 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001970 X509Names after the connection is set up.
1971 """
1972 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1973 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1974
1975 sedesc = secert.get_subject()
1976 cldesc = clcert.get_subject()
1977
1978 def multiple_ca(ctx):
1979 L = [sedesc, cldesc]
1980 ctx.set_client_ca_list(L)
1981 return L
1982 self._check_client_ca_list(multiple_ca)
1983
1984
1985 def test_reset_ca_list(self):
1986 """
1987 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09001988 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001989 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001990 """
1991 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1992 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1993 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1994
1995 cadesc = cacert.get_subject()
1996 sedesc = secert.get_subject()
1997 cldesc = clcert.get_subject()
1998
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001999 def changed_ca(ctx):
2000 ctx.set_client_ca_list([sedesc, cldesc])
2001 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002002 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002003 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002004
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002005
2006 def test_mutated_ca_list(self):
2007 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002008 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002009 afterwards, this does not affect the list of CA names sent to the
2010 client.
2011 """
2012 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2013 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2014
2015 cadesc = cacert.get_subject()
2016 sedesc = secert.get_subject()
2017
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002018 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002019 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002020 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002021 L.append(sedesc)
2022 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002023 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002024
2025
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002026 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002027 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002028 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002029 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002030 """
2031 ctx = Context(TLSv1_METHOD)
2032 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002033 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002034 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002035 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002036
2037
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002038 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002039 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002040 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09002041 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002042 """
2043 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2044 cadesc = cacert.get_subject()
2045 def single_ca(ctx):
2046 ctx.add_client_ca(cacert)
2047 return [cadesc]
2048 self._check_client_ca_list(single_ca)
2049
2050
2051 def test_multiple_add_client_ca(self):
2052 """
2053 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09002054 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002055 """
2056 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2057 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2058
2059 cadesc = cacert.get_subject()
2060 sedesc = secert.get_subject()
2061
2062 def multiple_ca(ctx):
2063 ctx.add_client_ca(cacert)
2064 ctx.add_client_ca(secert)
2065 return [cadesc, sedesc]
2066 self._check_client_ca_list(multiple_ca)
2067
2068
2069 def test_set_and_add_client_ca(self):
2070 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002071 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
2072 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002073 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002074 """
2075 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2076 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2077 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2078
2079 cadesc = cacert.get_subject()
2080 sedesc = secert.get_subject()
2081 cldesc = clcert.get_subject()
2082
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002083 def mixed_set_add_ca(ctx):
2084 ctx.set_client_ca_list([cadesc, sedesc])
2085 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002086 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002087 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002088
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002089
2090 def test_set_after_add_client_ca(self):
2091 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002092 A call to :py:obj:`Context.set_client_ca_list` after a call to
2093 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002094 call with the names specified by the latter cal.
2095 """
2096 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2097 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2098 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2099
2100 cadesc = cacert.get_subject()
2101 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002102
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002103 def set_replaces_add_ca(ctx):
2104 ctx.add_client_ca(clcert)
2105 ctx.set_client_ca_list([cadesc])
2106 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002107 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002108 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002109
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002110
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04002111class InfoConstantTests(TestCase):
2112 """
2113 Tests for assorted constants exposed for use in info callbacks.
2114 """
2115 def test_integers(self):
2116 """
2117 All of the info constants are integers.
2118
2119 This is a very weak test. It would be nice to have one that actually
2120 verifies that as certain info events happen, the value passed to the
2121 info callback matches up with the constant exposed by OpenSSL.SSL.
2122 """
2123 for const in [
2124 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
2125 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
2126 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
2127 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
2128 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
2129 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
2130
2131 self.assertTrue(isinstance(const, int))
2132
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02002133
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002134if __name__ == '__main__':
2135 main()