blob: 721c1c09c79fd4458ec0c06a0203eca78216f92f [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 Calderonee0fcf512012-02-13 09:10:15 -050037from OpenSSL.SSL import (
38 Context, ContextType, Session, Connection, ConnectionType)
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040039
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -040040from OpenSSL.test.util import TestCase, bytes, b
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040041from OpenSSL.test.test_crypto import (
42 cleartextCertificatePEM, cleartextPrivateKeyPEM)
43from OpenSSL.test.test_crypto import (
44 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
45 root_cert_pem)
46
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050047try:
48 from OpenSSL.SSL import OP_NO_QUERY_MTU
49except ImportError:
50 OP_NO_QUERY_MTU = None
51try:
52 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
53except ImportError:
54 OP_COOKIE_EXCHANGE = None
55try:
56 from OpenSSL.SSL import OP_NO_TICKET
57except ImportError:
58 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040059
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040060try:
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -040061 from OpenSSL.SSL import OP_NO_COMPRESSION
62except ImportError:
63 OP_NO_COMPRESSION = None
64
65try:
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040066 from OpenSSL.SSL import MODE_RELEASE_BUFFERS
67except ImportError:
68 MODE_RELEASE_BUFFERS = None
69
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040070from OpenSSL.SSL import (
71 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
72 SSL_ST_OK, SSL_ST_RENEGOTIATE,
73 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
74 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
75 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
76 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040077
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040078# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
79# to use)
80dhparam = """\
81-----BEGIN DH PARAMETERS-----
82MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
83-----END DH PARAMETERS-----
84"""
85
86
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040087def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040088 return ok
89
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040090
Rick Deanb1ccd562009-07-09 23:52:39 -050091def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040092 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -040093 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040094 """
95 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -050096 port = socket()
97 port.bind(('', 0))
98 port.listen(1)
99 client = socket()
100 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400101 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400102 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500103 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500104
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400105 # Let's pass some unencrypted data to make sure our socket connection is
106 # fine. Just one byte, so we don't have to worry about buffers getting
107 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400108 server.send(b("x"))
109 assert client.recv(1024) == b("x")
110 client.send(b("y"))
111 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500112
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400113 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400114 server.setblocking(False)
115 client.setblocking(False)
116
Rick Deanb1ccd562009-07-09 23:52:39 -0500117 return (server, client)
118
119
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400120
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400121def handshake(client, server):
122 conns = [client, server]
123 while conns:
124 for conn in conns:
125 try:
126 conn.do_handshake()
127 except WantReadError:
128 pass
129 else:
130 conns.remove(conn)
131
132
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400133def _create_certificate_chain():
134 """
135 Construct and return a chain of certificates.
136
137 1. A new self-signed certificate authority certificate (cacert)
138 2. A new intermediate certificate signed by cacert (icert)
139 3. A new server certificate signed by icert (scert)
140 """
141 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
142
143 # Step 1
144 cakey = PKey()
145 cakey.generate_key(TYPE_RSA, 512)
146 cacert = X509()
147 cacert.get_subject().commonName = "Authority Certificate"
148 cacert.set_issuer(cacert.get_subject())
149 cacert.set_pubkey(cakey)
150 cacert.set_notBefore(b("20000101000000Z"))
151 cacert.set_notAfter(b("20200101000000Z"))
152 cacert.add_extensions([caext])
153 cacert.set_serial_number(0)
154 cacert.sign(cakey, "sha1")
155
156 # Step 2
157 ikey = PKey()
158 ikey.generate_key(TYPE_RSA, 512)
159 icert = X509()
160 icert.get_subject().commonName = "Intermediate Certificate"
161 icert.set_issuer(cacert.get_subject())
162 icert.set_pubkey(ikey)
163 icert.set_notBefore(b("20000101000000Z"))
164 icert.set_notAfter(b("20200101000000Z"))
165 icert.add_extensions([caext])
166 icert.set_serial_number(0)
167 icert.sign(cakey, "sha1")
168
169 # Step 3
170 skey = PKey()
171 skey.generate_key(TYPE_RSA, 512)
172 scert = X509()
173 scert.get_subject().commonName = "Server Certificate"
174 scert.set_issuer(icert.get_subject())
175 scert.set_pubkey(skey)
176 scert.set_notBefore(b("20000101000000Z"))
177 scert.set_notAfter(b("20200101000000Z"))
178 scert.add_extensions([
179 X509Extension(b('basicConstraints'), True, b('CA:false'))])
180 scert.set_serial_number(0)
181 scert.sign(ikey, "sha1")
182
183 return [(cakey, cacert), (ikey, icert), (skey, scert)]
184
185
186
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400187class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400188 """
189 Helper mixin which defines methods for creating a connected socket pair and
190 for forcing two connected SSL sockets to talk to each other via memory BIOs.
191 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500192 def _loopbackClientFactory(self, socket):
193 client = Connection(Context(TLSv1_METHOD), socket)
194 client.set_connect_state()
195 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400196
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500197
198 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400199 ctx = Context(TLSv1_METHOD)
200 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
201 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500202 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400203 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500204 return server
205
206
207 def _loopback(self, serverFactory=None, clientFactory=None):
208 if serverFactory is None:
209 serverFactory = self._loopbackServerFactory
210 if clientFactory is None:
211 clientFactory = self._loopbackClientFactory
212
213 (server, client) = socket_pair()
214 server = serverFactory(server)
215 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400216
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400217 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400218
219 server.setblocking(True)
220 client.setblocking(True)
221 return server, client
222
223
224 def _interactInMemory(self, client_conn, server_conn):
225 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900226 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400227 objects. Copy bytes back and forth between their send/receive buffers
228 for as long as there is anything to copy. When there is nothing more
Jonathan Ballet648875f2011-07-16 14:14:58 +0900229 to copy, return :py:obj:`None`. If one of them actually manages to deliver
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400230 some application bytes, return a two-tuple of the connection from which
231 the bytes were read and the bytes themselves.
232 """
233 wrote = True
234 while wrote:
235 # Loop until neither side has anything to say
236 wrote = False
237
238 # Copy stuff from each side's send buffer to the other side's
239 # receive buffer.
240 for (read, write) in [(client_conn, server_conn),
241 (server_conn, client_conn)]:
242
243 # Give the side a chance to generate some more bytes, or
244 # succeed.
245 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400246 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400247 except WantReadError:
248 # It didn't succeed, so we'll hope it generated some
249 # output.
250 pass
251 else:
252 # It did succeed, so we'll stop now and let the caller deal
253 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400254 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400255
256 while True:
257 # Keep copying as long as there's more stuff there.
258 try:
259 dirty = read.bio_read(4096)
260 except WantReadError:
261 # Okay, nothing more waiting to be sent. Stop
262 # processing this send buffer.
263 break
264 else:
265 # Keep track of the fact that someone generated some
266 # output.
267 wrote = True
268 write.bio_write(dirty)
269
270
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400271
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400272class VersionTests(TestCase):
273 """
274 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900275 :py:obj:`OpenSSL.SSL.SSLeay_version` and
276 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400277 """
278 def test_OPENSSL_VERSION_NUMBER(self):
279 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900280 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400281 byte and the patch, fix, minor, and major versions in the
282 nibbles above that.
283 """
284 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
285
286
287 def test_SSLeay_version(self):
288 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900289 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400290 one of a number of version strings based on that indicator.
291 """
292 versions = {}
293 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
294 SSLEAY_PLATFORM, SSLEAY_DIR]:
295 version = SSLeay_version(t)
296 versions[version] = t
297 self.assertTrue(isinstance(version, bytes))
298 self.assertEqual(len(versions), 5)
299
300
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400301
302class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400303 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900304 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400305 """
306 def test_method(self):
307 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900308 :py:obj:`Context` can be instantiated with one of :py:obj:`SSLv2_METHOD`,
309 :py:obj:`SSLv3_METHOD`, :py:obj:`SSLv23_METHOD`, or :py:obj:`TLSv1_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400310 """
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400311 for meth in [SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400312 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400313
314 try:
315 Context(SSLv2_METHOD)
316 except ValueError:
317 # Some versions of OpenSSL have SSLv2, some don't.
318 # Difficult to say in advance.
319 pass
320
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400321 self.assertRaises(TypeError, Context, "")
322 self.assertRaises(ValueError, Context, 10)
323
324
Rick Deane15b1472009-07-09 15:53:42 -0500325 def test_type(self):
326 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900327 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400328 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500329 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400330 self.assertIdentical(Context, ContextType)
331 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500332
333
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400334 def test_use_privatekey(self):
335 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900336 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400337 """
338 key = PKey()
339 key.generate_key(TYPE_RSA, 128)
340 ctx = Context(TLSv1_METHOD)
341 ctx.use_privatekey(key)
342 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400343
344
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400345 def test_set_app_data_wrong_args(self):
346 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900347 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called with other than
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400348 one argument.
349 """
350 context = Context(TLSv1_METHOD)
351 self.assertRaises(TypeError, context.set_app_data)
352 self.assertRaises(TypeError, context.set_app_data, None, None)
353
354
355 def test_get_app_data_wrong_args(self):
356 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900357 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400358 arguments.
359 """
360 context = Context(TLSv1_METHOD)
361 self.assertRaises(TypeError, context.get_app_data, None)
362
363
364 def test_app_data(self):
365 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900366 :py:obj:`Context.set_app_data` stores an object for later retrieval using
367 :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400368 """
369 app_data = object()
370 context = Context(TLSv1_METHOD)
371 context.set_app_data(app_data)
372 self.assertIdentical(context.get_app_data(), app_data)
373
374
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400375 def test_set_options_wrong_args(self):
376 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900377 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with the wrong
378 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400379 """
380 context = Context(TLSv1_METHOD)
381 self.assertRaises(TypeError, context.set_options)
382 self.assertRaises(TypeError, context.set_options, None)
383 self.assertRaises(TypeError, context.set_options, 1, None)
384
385
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300386 def test_set_mode_wrong_args(self):
387 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400388 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with the wrong
389 number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300390 """
391 context = Context(TLSv1_METHOD)
392 self.assertRaises(TypeError, context.set_mode)
393 self.assertRaises(TypeError, context.set_mode, None)
394 self.assertRaises(TypeError, context.set_mode, 1, None)
395
396
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400397 if MODE_RELEASE_BUFFERS is not None:
398 def test_set_mode(self):
399 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400400 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the newly
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400401 set mode.
402 """
403 context = Context(TLSv1_METHOD)
404 self.assertTrue(
405 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
406 else:
407 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
408
409
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400410 def test_set_timeout_wrong_args(self):
411 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900412 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with the wrong
413 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400414 """
415 context = Context(TLSv1_METHOD)
416 self.assertRaises(TypeError, context.set_timeout)
417 self.assertRaises(TypeError, context.set_timeout, None)
418 self.assertRaises(TypeError, context.set_timeout, 1, None)
419
420
421 def test_get_timeout_wrong_args(self):
422 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900423 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400424 """
425 context = Context(TLSv1_METHOD)
426 self.assertRaises(TypeError, context.get_timeout, None)
427
428
429 def test_timeout(self):
430 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900431 :py:obj:`Context.set_timeout` sets the session timeout for all connections
432 created using the context object. :py:obj:`Context.get_timeout` retrieves this
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400433 value.
434 """
435 context = Context(TLSv1_METHOD)
436 context.set_timeout(1234)
437 self.assertEquals(context.get_timeout(), 1234)
438
439
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400440 def test_set_verify_depth_wrong_args(self):
441 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900442 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called with the wrong
443 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400444 """
445 context = Context(TLSv1_METHOD)
446 self.assertRaises(TypeError, context.set_verify_depth)
447 self.assertRaises(TypeError, context.set_verify_depth, None)
448 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
449
450
451 def test_get_verify_depth_wrong_args(self):
452 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900453 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400454 """
455 context = Context(TLSv1_METHOD)
456 self.assertRaises(TypeError, context.get_verify_depth, None)
457
458
459 def test_verify_depth(self):
460 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900461 :py:obj:`Context.set_verify_depth` sets the number of certificates in a chain
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400462 to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900463 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400464 """
465 context = Context(TLSv1_METHOD)
466 context.set_verify_depth(11)
467 self.assertEquals(context.get_verify_depth(), 11)
468
469
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400470 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400471 """
472 Write a new private key out to a new file, encrypted using the given
473 passphrase. Return the path to the new file.
474 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400475 key = PKey()
476 key.generate_key(TYPE_RSA, 128)
477 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400478 fObj = open(pemFile, 'w')
479 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
480 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400481 fObj.close()
482 return pemFile
483
484
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400485 def test_set_passwd_cb_wrong_args(self):
486 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900487 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called with the
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400488 wrong arguments or with a non-callable first argument.
489 """
490 context = Context(TLSv1_METHOD)
491 self.assertRaises(TypeError, context.set_passwd_cb)
492 self.assertRaises(TypeError, context.set_passwd_cb, None)
493 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
494
495
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400496 def test_set_passwd_cb(self):
497 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900498 :py:obj:`Context.set_passwd_cb` accepts a callable which will be invoked when
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400499 a private key is loaded from an encrypted PEM.
500 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400501 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400502 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400503 calledWith = []
504 def passphraseCallback(maxlen, verify, extra):
505 calledWith.append((maxlen, verify, extra))
506 return passphrase
507 context = Context(TLSv1_METHOD)
508 context.set_passwd_cb(passphraseCallback)
509 context.use_privatekey_file(pemFile)
510 self.assertTrue(len(calledWith), 1)
511 self.assertTrue(isinstance(calledWith[0][0], int))
512 self.assertTrue(isinstance(calledWith[0][1], int))
513 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400514
515
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400516 def test_passwd_callback_exception(self):
517 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900518 :py:obj:`Context.use_privatekey_file` propagates any exception raised by the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400519 passphrase callback.
520 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400521 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400522 def passphraseCallback(maxlen, verify, extra):
523 raise RuntimeError("Sorry, I am a fail.")
524
525 context = Context(TLSv1_METHOD)
526 context.set_passwd_cb(passphraseCallback)
527 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
528
529
530 def test_passwd_callback_false(self):
531 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900532 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400533 passphrase callback returns a false value.
534 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400535 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400536 def passphraseCallback(maxlen, verify, extra):
537 return None
538
539 context = Context(TLSv1_METHOD)
540 context.set_passwd_cb(passphraseCallback)
541 self.assertRaises(Error, context.use_privatekey_file, pemFile)
542
543
544 def test_passwd_callback_non_string(self):
545 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900546 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400547 passphrase callback returns a true non-string value.
548 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400549 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400550 def passphraseCallback(maxlen, verify, extra):
551 return 10
552
553 context = Context(TLSv1_METHOD)
554 context.set_passwd_cb(passphraseCallback)
555 self.assertRaises(Error, context.use_privatekey_file, pemFile)
556
557
558 def test_passwd_callback_too_long(self):
559 """
560 If the passphrase returned by the passphrase callback returns a string
561 longer than the indicated maximum length, it is truncated.
562 """
563 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400564 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400565 pemFile = self._write_encrypted_pem(passphrase)
566 def passphraseCallback(maxlen, verify, extra):
567 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400568 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400569
570 context = Context(TLSv1_METHOD)
571 context.set_passwd_cb(passphraseCallback)
572 # This shall succeed because the truncated result is the correct
573 # passphrase.
574 context.use_privatekey_file(pemFile)
575
576
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400577 def test_set_info_callback(self):
578 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900579 :py:obj:`Context.set_info_callback` accepts a callable which will be invoked
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400580 when certain information about an SSL connection is available.
581 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500582 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400583
584 clientSSL = Connection(Context(TLSv1_METHOD), client)
585 clientSSL.set_connect_state()
586
587 called = []
588 def info(conn, where, ret):
589 called.append((conn, where, ret))
590 context = Context(TLSv1_METHOD)
591 context.set_info_callback(info)
592 context.use_certificate(
593 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
594 context.use_privatekey(
595 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
596
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400597 serverSSL = Connection(context, server)
598 serverSSL.set_accept_state()
599
600 while not called:
601 for ssl in clientSSL, serverSSL:
602 try:
603 ssl.do_handshake()
604 except WantReadError:
605 pass
606
607 # Kind of lame. Just make sure it got called somehow.
608 self.assertTrue(called)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400609
610
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400611 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400612 """
613 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400614 its :py:obj:`load_verify_locations` method with the given arguments.
615 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400616 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500617 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400618
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400619 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400620 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400621 # Require that the server certificate verify properly or the
622 # connection will fail.
623 clientContext.set_verify(
624 VERIFY_PEER,
625 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
626
627 clientSSL = Connection(clientContext, client)
628 clientSSL.set_connect_state()
629
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400630 serverContext = Context(TLSv1_METHOD)
631 serverContext.use_certificate(
632 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
633 serverContext.use_privatekey(
634 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
635
636 serverSSL = Connection(serverContext, server)
637 serverSSL.set_accept_state()
638
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400639 # Without load_verify_locations above, the handshake
640 # will fail:
641 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
642 # 'certificate verify failed')]
643 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400644
645 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400646 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400647
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500648
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400649 def test_load_verify_file(self):
650 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900651 :py:obj:`Context.load_verify_locations` accepts a file name and uses the
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400652 certificates within for verification purposes.
653 """
654 cafile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400655 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400656 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400657 fObj.close()
658
659 self._load_verify_locations_test(cafile)
660
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400661
662 def test_load_verify_invalid_file(self):
663 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900664 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when passed a
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400665 non-existent cafile.
666 """
667 clientContext = Context(TLSv1_METHOD)
668 self.assertRaises(
669 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400670
671
672 def test_load_verify_directory(self):
673 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900674 :py:obj:`Context.load_verify_locations` accepts a directory name and uses
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400675 the certificates within for verification purposes.
676 """
677 capath = self.mktemp()
678 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400679 # Hash values computed manually with c_rehash to avoid depending on
680 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
681 # from OpenSSL 1.0.0.
682 for name in ['c7adac82.0', 'c3705638.0']:
683 cafile = join(capath, name)
684 fObj = open(cafile, 'w')
685 fObj.write(cleartextCertificatePEM.decode('ascii'))
686 fObj.close()
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400687
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400688 self._load_verify_locations_test(None, capath)
689
690
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400691 def test_load_verify_locations_wrong_args(self):
692 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900693 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if called with
694 the wrong number of arguments or with non-:py:obj:`str` arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400695 """
696 context = Context(TLSv1_METHOD)
697 self.assertRaises(TypeError, context.load_verify_locations)
698 self.assertRaises(TypeError, context.load_verify_locations, object())
699 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
700 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
701
702
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400703 if platform == "win32":
704 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400705 "See LP#404343 and LP#404344."
706 else:
707 def test_set_default_verify_paths(self):
708 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900709 :py:obj:`Context.set_default_verify_paths` causes the platform-specific CA
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400710 certificate locations to be used for verification purposes.
711 """
712 # Testing this requires a server with a certificate signed by one of
713 # the CAs in the platform CA location. Getting one of those costs
714 # money. Fortunately (or unfortunately, depending on your
715 # perspective), it's easy to think of a public server on the
716 # internet which has such a certificate. Connecting to the network
717 # in a unit test is bad, but it's the only way I can think of to
718 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400719
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400720 # Arg, verisign.com doesn't speak TLSv1
721 context = Context(SSLv3_METHOD)
722 context.set_default_verify_paths()
723 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +0200724 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400725 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400726
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400727 client = socket()
728 client.connect(('verisign.com', 443))
729 clientSSL = Connection(context, client)
730 clientSSL.set_connect_state()
731 clientSSL.do_handshake()
732 clientSSL.send('GET / HTTP/1.0\r\n\r\n')
733 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400734
735
736 def test_set_default_verify_paths_signature(self):
737 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900738 :py:obj:`Context.set_default_verify_paths` takes no arguments and raises
739 :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400740 """
741 context = Context(TLSv1_METHOD)
742 self.assertRaises(TypeError, context.set_default_verify_paths, None)
743 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
744 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500745
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400746
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500747 def test_add_extra_chain_cert_invalid_cert(self):
748 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900749 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if called with
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500750 other than one argument or if called with an object which is not an
Jonathan Ballet648875f2011-07-16 14:14:58 +0900751 instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500752 """
753 context = Context(TLSv1_METHOD)
754 self.assertRaises(TypeError, context.add_extra_chain_cert)
755 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
756 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
757
758
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400759 def _handshake_test(self, serverContext, clientContext):
760 """
761 Verify that a client and server created with the given contexts can
762 successfully handshake and communicate.
763 """
764 serverSocket, clientSocket = socket_pair()
765
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400766 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400767 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400768
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400769 client = Connection(clientContext, clientSocket)
770 client.set_connect_state()
771
772 # Make them talk to each other.
773 # self._interactInMemory(client, server)
774 for i in range(3):
775 for s in [client, server]:
776 try:
777 s.do_handshake()
778 except WantReadError:
779 pass
780
781
782 def test_add_extra_chain_cert(self):
783 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900784 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509` instance to add to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400785 the certificate chain.
786
Jonathan Ballet648875f2011-07-16 14:14:58 +0900787 See :py:obj:`_create_certificate_chain` for the details of the certificate
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400788 chain tested.
789
790 The chain is tested by starting a server with scert and connecting
791 to it with a client which trusts cacert and requires verification to
792 succeed.
793 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400794 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400795 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
796
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400797 # Dump the CA certificate to a file because that's the only way to load
798 # it as a trusted CA in the client context.
799 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400800 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400801 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400802 fObj.close()
803
804 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400805 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400806 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400807 fObj.close()
808
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400809 # Create the server context
810 serverContext = Context(TLSv1_METHOD)
811 serverContext.use_privatekey(skey)
812 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400813 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400814 serverContext.add_extra_chain_cert(icert)
815
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400816 # Create the client
817 clientContext = Context(TLSv1_METHOD)
818 clientContext.set_verify(
819 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
820 clientContext.load_verify_locations('ca.pem')
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400821
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400822 # Try it out.
823 self._handshake_test(serverContext, clientContext)
824
825
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400826 def test_use_certificate_chain_file(self):
827 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900828 :py:obj:`Context.use_certificate_chain_file` reads a certificate chain from
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400829 the specified file.
830
831 The chain is tested by starting a server with scert and connecting
832 to it with a client which trusts cacert and requires verification to
833 succeed.
834 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400835 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400836 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
837
838 # Write out the chain file.
839 chainFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400840 fObj = open(chainFile, 'w')
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400841 # Most specific to least general.
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400842 fObj.write(dump_certificate(FILETYPE_PEM, scert).decode('ascii'))
843 fObj.write(dump_certificate(FILETYPE_PEM, icert).decode('ascii'))
844 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400845 fObj.close()
846
847 serverContext = Context(TLSv1_METHOD)
848 serverContext.use_certificate_chain_file(chainFile)
849 serverContext.use_privatekey(skey)
850
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400851 fObj = open('ca.pem', 'w')
852 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400853 fObj.close()
854
855 clientContext = Context(TLSv1_METHOD)
856 clientContext.set_verify(
857 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
858 clientContext.load_verify_locations('ca.pem')
859
860 self._handshake_test(serverContext, clientContext)
861
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -0400862 # XXX load_client_ca
863 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -0400864
865 def test_get_verify_mode_wrong_args(self):
866 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900867 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -0400868 arguments.
869 """
870 context = Context(TLSv1_METHOD)
871 self.assertRaises(TypeError, context.get_verify_mode, None)
872
873
874 def test_get_verify_mode(self):
875 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900876 :py:obj:`Context.get_verify_mode` returns the verify mode flags previously
877 passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -0400878 """
879 context = Context(TLSv1_METHOD)
880 self.assertEquals(context.get_verify_mode(), 0)
881 context.set_verify(
882 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
883 self.assertEquals(
884 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
885
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400886
887 def test_load_tmp_dh_wrong_args(self):
888 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900889 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
890 number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400891 """
892 context = Context(TLSv1_METHOD)
893 self.assertRaises(TypeError, context.load_tmp_dh)
894 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
895 self.assertRaises(TypeError, context.load_tmp_dh, object())
896
897
898 def test_load_tmp_dh_missing_file(self):
899 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900900 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the specified file
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400901 does not exist.
902 """
903 context = Context(TLSv1_METHOD)
904 self.assertRaises(Error, context.load_tmp_dh, "hello")
905
906
907 def test_load_tmp_dh(self):
908 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900909 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400910 specified file.
911 """
912 context = Context(TLSv1_METHOD)
913 dhfilename = self.mktemp()
914 dhfile = open(dhfilename, "w")
915 dhfile.write(dhparam)
916 dhfile.close()
917 context.load_tmp_dh(dhfilename)
918 # XXX What should I assert here? -exarkun
919
920
921 def test_set_cipher_list(self):
922 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900923 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`str` naming the ciphers which
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400924 connections created with the context object will be able to choose from.
925 """
926 context = Context(TLSv1_METHOD)
927 context.set_cipher_list("hello world:EXP-RC4-MD5")
928 conn = Connection(context, None)
929 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400930
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400931
Jean-Paul Calderone313bf012012-02-08 13:02:49 -0500932 def test_set_session_cache_mode_wrong_args(self):
933 """
934 L{Context.set_session_cache_mode} raises L{TypeError} if called with
935 other than one integer argument.
936 """
937 context = Context(TLSv1_METHOD)
938 self.assertRaises(TypeError, context.set_session_cache_mode)
939 self.assertRaises(TypeError, context.set_session_cache_mode, object())
940
941
942 def test_get_session_cache_mode_wrong_args(self):
943 """
944 L{Context.get_session_cache_mode} raises L{TypeError} if called with any
945 arguments.
946 """
947 context = Context(TLSv1_METHOD)
948 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
949
950
951 def test_session_cache_mode(self):
952 """
953 L{Context.set_session_cache_mode} specifies how sessions are cached.
954 The setting can be retrieved via L{Context.get_session_cache_mode}.
955 """
956 context = Context(TLSv1_METHOD)
957 old = context.set_session_cache_mode(SESS_CACHE_OFF)
958 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
959 self.assertEqual(SESS_CACHE_OFF, off)
960 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
961
962
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400963
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -0400964class ServerNameCallbackTests(TestCase, _LoopbackMixin):
965 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900966 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
967 :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -0400968 """
969 def test_wrong_args(self):
970 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900971 :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -0400972 with other than one argument.
973 """
974 context = Context(TLSv1_METHOD)
975 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
976 self.assertRaises(
977 TypeError, context.set_tlsext_servername_callback, 1, 2)
978
979 def test_old_callback_forgotten(self):
980 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900981 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -0400982 callback, the one it replaces is dereferenced.
983 """
984 def callback(connection):
985 pass
986
987 def replacement(connection):
988 pass
989
990 context = Context(TLSv1_METHOD)
991 context.set_tlsext_servername_callback(callback)
992
993 tracker = ref(callback)
994 del callback
995
996 context.set_tlsext_servername_callback(replacement)
997 collect()
998 self.assertIdentical(None, tracker())
999
1000
1001 def test_no_servername(self):
1002 """
1003 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001004 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
1005 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001006 """
1007 args = []
1008 def servername(conn):
1009 args.append((conn, conn.get_servername()))
1010 context = Context(TLSv1_METHOD)
1011 context.set_tlsext_servername_callback(servername)
1012
1013 # Lose our reference to it. The Context is responsible for keeping it
1014 # alive now.
1015 del servername
1016 collect()
1017
1018 # Necessary to actually accept the connection
1019 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1020 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1021
1022 # Do a little connection to trigger the logic
1023 server = Connection(context, None)
1024 server.set_accept_state()
1025
1026 client = Connection(Context(TLSv1_METHOD), None)
1027 client.set_connect_state()
1028
1029 self._interactInMemory(server, client)
1030
1031 self.assertEqual([(server, None)], args)
1032
1033
1034 def test_servername(self):
1035 """
1036 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +09001037 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
1038 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001039 """
1040 args = []
1041 def servername(conn):
1042 args.append((conn, conn.get_servername()))
1043 context = Context(TLSv1_METHOD)
1044 context.set_tlsext_servername_callback(servername)
1045
1046 # Necessary to actually accept the connection
1047 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1048 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1049
1050 # Do a little connection to trigger the logic
1051 server = Connection(context, None)
1052 server.set_accept_state()
1053
1054 client = Connection(Context(TLSv1_METHOD), None)
1055 client.set_connect_state()
1056 client.set_tlsext_host_name(b("foo1.example.com"))
1057
1058 self._interactInMemory(server, client)
1059
1060 self.assertEqual([(server, b("foo1.example.com"))], args)
1061
1062
1063
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001064class SessionTests(TestCase):
1065 """
1066 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1067 """
1068 def test_construction(self):
1069 """
1070 :py:class:`Session` can be constructed with no arguments, creating a new
1071 instance of that type.
1072 """
1073 new_session = Session()
1074 self.assertTrue(isinstance(new_session, Session))
1075
1076
1077 def test_construction_wrong_args(self):
1078 """
1079 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
1080 is raised.
1081 """
1082 self.assertRaises(TypeError, Session, 123)
1083 self.assertRaises(TypeError, Session, "hello")
1084 self.assertRaises(TypeError, Session, object())
1085
1086
1087
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001088class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05001089 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001090 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001091 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001092 # XXX want_write
1093 # XXX want_read
1094 # XXX get_peer_certificate -> None
1095 # XXX sock_shutdown
1096 # XXX master_key -> TypeError
1097 # XXX server_random -> TypeError
1098 # XXX state_string
1099 # XXX connect -> TypeError
1100 # XXX connect_ex -> TypeError
1101 # XXX set_connect_state -> TypeError
1102 # XXX set_accept_state -> TypeError
1103 # XXX renegotiate_pending
1104 # XXX do_handshake -> TypeError
1105 # XXX bio_read -> TypeError
1106 # XXX recv -> TypeError
1107 # XXX send -> TypeError
1108 # XXX bio_write -> TypeError
1109
Rick Deane15b1472009-07-09 15:53:42 -05001110 def test_type(self):
1111 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001112 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001113 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05001114 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001115 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05001116 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001117 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05001118
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001119
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001120 def test_get_context(self):
1121 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001122 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
1123 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001124 """
1125 context = Context(TLSv1_METHOD)
1126 connection = Connection(context, None)
1127 self.assertIdentical(connection.get_context(), context)
1128
1129
1130 def test_get_context_wrong_args(self):
1131 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001132 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001133 arguments.
1134 """
1135 connection = Connection(Context(TLSv1_METHOD), None)
1136 self.assertRaises(TypeError, connection.get_context, None)
1137
1138
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001139 def test_set_context_wrong_args(self):
1140 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001141 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
1142 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001143 than 1.
1144 """
1145 ctx = Context(TLSv1_METHOD)
1146 connection = Connection(ctx, None)
1147 self.assertRaises(TypeError, connection.set_context)
1148 self.assertRaises(TypeError, connection.set_context, object())
1149 self.assertRaises(TypeError, connection.set_context, "hello")
1150 self.assertRaises(TypeError, connection.set_context, 1)
1151 self.assertRaises(TypeError, connection.set_context, 1, 2)
1152 self.assertRaises(
1153 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
1154 self.assertIdentical(ctx, connection.get_context())
1155
1156
1157 def test_set_context(self):
1158 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001159 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001160 for the connection.
1161 """
1162 original = Context(SSLv23_METHOD)
1163 replacement = Context(TLSv1_METHOD)
1164 connection = Connection(original, None)
1165 connection.set_context(replacement)
1166 self.assertIdentical(replacement, connection.get_context())
1167 # Lose our references to the contexts, just in case the Connection isn't
1168 # properly managing its own contributions to their reference counts.
1169 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001170 collect()
1171
1172
1173 def test_set_tlsext_host_name_wrong_args(self):
1174 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001175 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001176 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09001177 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001178 """
1179 conn = Connection(Context(TLSv1_METHOD), None)
1180 self.assertRaises(TypeError, conn.set_tlsext_host_name)
1181 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
1182 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
1183 self.assertRaises(
1184 TypeError, conn.set_tlsext_host_name, b("with\0null"))
1185
1186 if version_info >= (3,):
1187 # On Python 3.x, don't accidentally implicitly convert from text.
1188 self.assertRaises(
1189 TypeError,
1190 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001191
1192
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001193 def test_get_servername_wrong_args(self):
1194 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001195 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001196 arguments.
1197 """
1198 connection = Connection(Context(TLSv1_METHOD), None)
1199 self.assertRaises(TypeError, connection.get_servername, object())
1200 self.assertRaises(TypeError, connection.get_servername, 1)
1201 self.assertRaises(TypeError, connection.get_servername, "hello")
1202
1203
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001204 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001205 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001206 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001207 immediate read.
1208 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001209 connection = Connection(Context(TLSv1_METHOD), None)
1210 self.assertEquals(connection.pending(), 0)
1211
1212
1213 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001214 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001215 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001216 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001217 connection = Connection(Context(TLSv1_METHOD), None)
1218 self.assertRaises(TypeError, connection.pending, None)
1219
1220
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001221 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001222 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001223 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001224 argument or with the wrong number of arguments.
1225 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001226 connection = Connection(Context(TLSv1_METHOD), socket())
1227 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001228 self.assertRaises(TypeError, connection.connect)
1229 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001230
1231
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001232 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001233 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001234 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001235 connect method raises it.
1236 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001237 client = socket()
1238 context = Context(TLSv1_METHOD)
1239 clientSSL = Connection(context, client)
1240 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04001241 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001242
1243
1244 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001245 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001246 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001247 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001248 port = socket()
1249 port.bind(('', 0))
1250 port.listen(3)
1251
1252 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001253 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
1254 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001255
1256
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001257 if platform == "darwin":
1258 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
1259 else:
1260 def test_connect_ex(self):
1261 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001262 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001263 errno instead of raising an exception.
1264 """
1265 port = socket()
1266 port.bind(('', 0))
1267 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001268
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001269 clientSSL = Connection(Context(TLSv1_METHOD), socket())
1270 clientSSL.setblocking(False)
1271 result = clientSSL.connect_ex(port.getsockname())
1272 expected = (EINPROGRESS, EWOULDBLOCK)
1273 self.assertTrue(
1274 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001275
1276
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001277 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001278 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001279 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001280 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001281 connection = Connection(Context(TLSv1_METHOD), socket())
1282 self.assertRaises(TypeError, connection.accept, None)
1283
1284
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001285 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001286 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001287 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
1288 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001289 connection originated from.
1290 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001291 ctx = Context(TLSv1_METHOD)
1292 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1293 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001294 port = socket()
1295 portSSL = Connection(ctx, port)
1296 portSSL.bind(('', 0))
1297 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001298
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001299 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001300
1301 # Calling portSSL.getsockname() here to get the server IP address sounds
1302 # great, but frequently fails on Windows.
1303 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001304
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001305 serverSSL, address = portSSL.accept()
1306
1307 self.assertTrue(isinstance(serverSSL, Connection))
1308 self.assertIdentical(serverSSL.get_context(), ctx)
1309 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001310
1311
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001312 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001313 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001314 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001315 number of arguments or with arguments other than integers.
1316 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001317 connection = Connection(Context(TLSv1_METHOD), None)
1318 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04001319 self.assertRaises(TypeError, connection.get_shutdown, None)
1320 self.assertRaises(TypeError, connection.set_shutdown)
1321 self.assertRaises(TypeError, connection.set_shutdown, None)
1322 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001323
1324
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001325 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001326 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001327 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001328 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001329 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001330 self.assertFalse(server.shutdown())
1331 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001332 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001333 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
1334 client.shutdown()
1335 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
1336 self.assertRaises(ZeroReturnError, server.recv, 1024)
1337 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001338
1339
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001340 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001341 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001342 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001343 process.
1344 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001345 connection = Connection(Context(TLSv1_METHOD), socket())
1346 connection.set_shutdown(RECEIVED_SHUTDOWN)
1347 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1348
1349
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001350 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001351 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001352 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
1353 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001354 with any arguments.
1355 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001356 conn = Connection(Context(TLSv1_METHOD), None)
1357 self.assertRaises(TypeError, conn.get_app_data, None)
1358 self.assertRaises(TypeError, conn.set_app_data)
1359 self.assertRaises(TypeError, conn.set_app_data, None, None)
1360
1361
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001362 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001363 """
1364 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001365 :py:obj:`Connection.set_app_data` and later retrieved with
1366 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001367 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001368 conn = Connection(Context(TLSv1_METHOD), None)
1369 app_data = object()
1370 conn.set_app_data(app_data)
1371 self.assertIdentical(conn.get_app_data(), app_data)
1372
1373
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001374 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001375 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001376 :py:obj:`Connection.makefile` is not implemented and calling that method raises
1377 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001378 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001379 conn = Connection(Context(TLSv1_METHOD), None)
1380 self.assertRaises(NotImplementedError, conn.makefile)
1381
1382
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001383 def test_get_peer_cert_chain_wrong_args(self):
1384 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001385 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001386 arguments.
1387 """
1388 conn = Connection(Context(TLSv1_METHOD), None)
1389 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
1390 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
1391 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
1392 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
1393
1394
1395 def test_get_peer_cert_chain(self):
1396 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001397 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001398 the connected server returned for the certification verification.
1399 """
1400 chain = _create_certificate_chain()
1401 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1402
1403 serverContext = Context(TLSv1_METHOD)
1404 serverContext.use_privatekey(skey)
1405 serverContext.use_certificate(scert)
1406 serverContext.add_extra_chain_cert(icert)
1407 serverContext.add_extra_chain_cert(cacert)
1408 server = Connection(serverContext, None)
1409 server.set_accept_state()
1410
1411 # Create the client
1412 clientContext = Context(TLSv1_METHOD)
1413 clientContext.set_verify(VERIFY_NONE, verify_cb)
1414 client = Connection(clientContext, None)
1415 client.set_connect_state()
1416
1417 self._interactInMemory(client, server)
1418
1419 chain = client.get_peer_cert_chain()
1420 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001421 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001422 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001423 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001424 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001425 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001426 "Authority Certificate", chain[2].get_subject().CN)
1427
1428
1429 def test_get_peer_cert_chain_none(self):
1430 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001431 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001432 certificate chain.
1433 """
1434 ctx = Context(TLSv1_METHOD)
1435 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1436 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1437 server = Connection(ctx, None)
1438 server.set_accept_state()
1439 client = Connection(Context(TLSv1_METHOD), None)
1440 client.set_connect_state()
1441 self._interactInMemory(client, server)
1442 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001443
1444
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001445 def test_get_session_wrong_args(self):
1446 """
1447 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
1448 with any arguments.
1449 """
1450 ctx = Context(TLSv1_METHOD)
1451 server = Connection(ctx, None)
1452 self.assertRaises(TypeError, server.get_session, 123)
1453 self.assertRaises(TypeError, server.get_session, "hello")
1454 self.assertRaises(TypeError, server.get_session, object())
1455
1456
1457 def test_get_session_unconnected(self):
1458 """
1459 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
1460 an object which has not been connected.
1461 """
1462 ctx = Context(TLSv1_METHOD)
1463 server = Connection(ctx, None)
1464 session = server.get_session()
1465 self.assertIdentical(None, session)
1466
1467
1468 def test_server_get_session(self):
1469 """
1470 On the server side of a connection, :py:obj:`Connection.get_session`
1471 returns a :py:class:`Session` instance representing the SSL session for
1472 that connection.
1473 """
1474 server, client = self._loopback()
1475 session = server.get_session()
1476 self.assertTrue(session, Session)
1477
1478
1479 def test_client_get_session(self):
1480 """
1481 On the client side of a connection, :py:obj:`Connection.get_session`
1482 returns a :py:class:`Session` instance representing the SSL session for
1483 that connection.
1484 """
1485 server, client = self._loopback()
1486 session = client.get_session()
1487 self.assertTrue(session, Session)
1488
1489
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05001490 def test_set_session_wrong_args(self):
1491 """
1492 If called with an object that is not an instance of :py:class:`Session`,
1493 or with other than one argument, :py:obj:`Connection.set_session` raises
1494 :py:obj:`TypeError`.
1495 """
1496 ctx = Context(TLSv1_METHOD)
1497 connection = Connection(ctx, None)
1498 self.assertRaises(TypeError, connection.set_session)
1499 self.assertRaises(TypeError, connection.set_session, 123)
1500 self.assertRaises(TypeError, connection.set_session, "hello")
1501 self.assertRaises(TypeError, connection.set_session, object())
1502 self.assertRaises(
1503 TypeError, connection.set_session, Session(), Session())
1504
1505
1506 def test_client_set_session(self):
1507 """
1508 :py:obj:`Connection.set_session`, when used prior to a connection being
1509 established, accepts a :py:class:`Session` instance and causes an
1510 attempt to re-use the session it represents when the SSL handshake is
1511 performed.
1512 """
1513 key = load_privatekey(FILETYPE_PEM, server_key_pem)
1514 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
1515 ctx = Context(TLSv1_METHOD)
1516 ctx.use_privatekey(key)
1517 ctx.use_certificate(cert)
1518 ctx.set_session_id("unity-test")
1519
1520 def makeServer(socket):
1521 server = Connection(ctx, socket)
1522 server.set_accept_state()
1523 return server
1524
1525 originalServer, originalClient = self._loopback(
1526 serverFactory=makeServer)
1527 originalSession = originalClient.get_session()
1528
1529 def makeClient(socket):
1530 client = self._loopbackClientFactory(socket)
1531 client.set_session(originalSession)
1532 return client
1533 resumedServer, resumedClient = self._loopback(
1534 serverFactory=makeServer,
1535 clientFactory=makeClient)
1536
1537 # This is a proxy: in general, we have no access to any unique
1538 # identifier for the session (new enough versions of OpenSSL expose a
1539 # hash which could be usable, but "new enough" is very, very new).
1540 # Instead, exploit the fact that the master key is re-used if the
1541 # session is re-used. As long as the master key for the two connections
1542 # is the same, the session was re-used!
1543 self.assertEqual(
1544 originalServer.master_key(), resumedServer.master_key())
1545
1546
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05001547 def test_set_session_wrong_method(self):
1548 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05001549 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
1550 instance associated with a context using a different SSL method than the
1551 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
1552 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05001553 """
1554 key = load_privatekey(FILETYPE_PEM, server_key_pem)
1555 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
1556 ctx = Context(TLSv1_METHOD)
1557 ctx.use_privatekey(key)
1558 ctx.use_certificate(cert)
1559 ctx.set_session_id("unity-test")
1560
1561 def makeServer(socket):
1562 server = Connection(ctx, socket)
1563 server.set_accept_state()
1564 return server
1565
1566 originalServer, originalClient = self._loopback(
1567 serverFactory=makeServer)
1568 originalSession = originalClient.get_session()
1569
1570 def makeClient(socket):
1571 # Intentionally use a different, incompatible method here.
1572 client = Connection(Context(SSLv3_METHOD), socket)
1573 client.set_connect_state()
1574 client.set_session(originalSession)
1575 return client
1576
1577 self.assertRaises(
1578 Error,
1579 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
1580
1581
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001582
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001583class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001584 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001585 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001586 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04001587 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001588 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001589 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001590 arguments.
1591 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001592 connection = Connection(Context(TLSv1_METHOD), None)
1593 self.assertRaises(TypeError, connection.get_cipher_list, None)
1594
1595
1596 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001597 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001598 :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 -04001599 names of the ciphers which might be used.
1600 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001601 connection = Connection(Context(TLSv1_METHOD), None)
1602 ciphers = connection.get_cipher_list()
1603 self.assertTrue(isinstance(ciphers, list))
1604 for cipher in ciphers:
1605 self.assertTrue(isinstance(cipher, str))
1606
1607
1608
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001609class ConnectionSendTests(TestCase, _LoopbackMixin):
1610 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001611 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001612 """
1613 def test_wrong_args(self):
1614 """
1615 When called with arguments other than a single string,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001616 :py:obj:`Connection.send` raises :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001617 """
1618 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05001619 self.assertRaises(TypeError, connection.send)
1620 self.assertRaises(TypeError, connection.send, object())
1621 self.assertRaises(TypeError, connection.send, "foo", "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001622
1623
1624 def test_short_bytes(self):
1625 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001626 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001627 and returns the number of bytes sent.
1628 """
1629 server, client = self._loopback()
1630 count = server.send(b('xy'))
1631 self.assertEquals(count, 2)
1632 self.assertEquals(client.recv(2), b('xy'))
1633
1634 try:
1635 memoryview
1636 except NameError:
1637 "cannot test sending memoryview without memoryview"
1638 else:
1639 def test_short_memoryview(self):
1640 """
1641 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001642 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001643 bytes sent.
1644 """
1645 server, client = self._loopback()
1646 count = server.send(memoryview(b('xy')))
1647 self.assertEquals(count, 2)
1648 self.assertEquals(client.recv(2), b('xy'))
1649
1650
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05001651
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001652class ConnectionSendallTests(TestCase, _LoopbackMixin):
1653 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001654 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001655 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001656 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001657 """
1658 When called with arguments other than a single string,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001659 :py:obj:`Connection.sendall` raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001660 """
1661 connection = Connection(Context(TLSv1_METHOD), None)
1662 self.assertRaises(TypeError, connection.sendall)
1663 self.assertRaises(TypeError, connection.sendall, object())
1664 self.assertRaises(TypeError, connection.sendall, "foo", "bar")
1665
1666
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001667 def test_short(self):
1668 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001669 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001670 it.
1671 """
1672 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001673 server.sendall(b('x'))
1674 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001675
1676
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05001677 try:
1678 memoryview
1679 except NameError:
1680 "cannot test sending memoryview without memoryview"
1681 else:
1682 def test_short_memoryview(self):
1683 """
1684 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001685 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05001686 """
1687 server, client = self._loopback()
1688 server.sendall(memoryview(b('x')))
1689 self.assertEquals(client.recv(1), b('x'))
1690
1691
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001692 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001693 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001694 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001695 it even if this requires multiple calls of an underlying write function.
1696 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001697 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04001698 # Should be enough, underlying SSL_write should only do 16k at a time.
1699 # On Windows, after 32k of bytes the write will block (forever - because
1700 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04001701 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001702 server.sendall(message)
1703 accum = []
1704 received = 0
1705 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001706 data = client.recv(1024)
1707 accum.append(data)
1708 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04001709 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001710
1711
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001712 def test_closed(self):
1713 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001714 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001715 write error from the low level write call.
1716 """
1717 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04001718 server.sock_shutdown(2)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001719 self.assertRaises(SysCallError, server.sendall, "hello, world")
1720
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001721
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001722
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001723class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
1724 """
1725 Tests for SSL renegotiation APIs.
1726 """
1727 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001728 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001729 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001730 arguments.
1731 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001732 connection = Connection(Context(TLSv1_METHOD), None)
1733 self.assertRaises(TypeError, connection.renegotiate, None)
1734
1735
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001736 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001737 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001738 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001739 any arguments.
1740 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001741 connection = Connection(Context(TLSv1_METHOD), None)
1742 self.assertRaises(TypeError, connection.total_renegotiations, None)
1743
1744
1745 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001746 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001747 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001748 renegotiations have happened.
1749 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001750 connection = Connection(Context(TLSv1_METHOD), None)
1751 self.assertEquals(connection.total_renegotiations(), 0)
1752
1753
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001754# def test_renegotiate(self):
1755# """
1756# """
1757# server, client = self._loopback()
1758
1759# server.send("hello world")
1760# self.assertEquals(client.recv(len("hello world")), "hello world")
1761
1762# self.assertEquals(server.total_renegotiations(), 0)
1763# self.assertTrue(server.renegotiate())
1764
1765# server.setblocking(False)
1766# client.setblocking(False)
1767# while server.renegotiate_pending():
1768# client.do_handshake()
1769# server.do_handshake()
1770
1771# self.assertEquals(server.total_renegotiations(), 1)
1772
1773
1774
1775
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001776class ErrorTests(TestCase):
1777 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001778 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001779 """
1780 def test_type(self):
1781 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001782 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001783 """
1784 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05001785 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05001786
1787
1788
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001789class ConstantsTests(TestCase):
1790 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001791 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001792
1793 These are values defined by OpenSSL intended only to be used as flags to
1794 OpenSSL APIs. The only assertions it seems can be made about them is
1795 their values.
1796 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001797 # unittest.TestCase has no skip mechanism
1798 if OP_NO_QUERY_MTU is not None:
1799 def test_op_no_query_mtu(self):
1800 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001801 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001802 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001803 """
1804 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
1805 else:
1806 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001807
1808
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001809 if OP_COOKIE_EXCHANGE is not None:
1810 def test_op_cookie_exchange(self):
1811 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001812 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001813 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001814 """
1815 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
1816 else:
1817 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001818
1819
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001820 if OP_NO_TICKET is not None:
1821 def test_op_no_ticket(self):
1822 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001823 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001824 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001825 """
1826 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04001827 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001828 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05001829
1830
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04001831 if OP_NO_COMPRESSION is not None:
1832 def test_op_no_compression(self):
1833 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001834 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
1835 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04001836 """
1837 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
1838 else:
1839 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
1840
1841
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001842 def test_sess_cache_off(self):
1843 """
1844 The value of L{OpenSSL.SSL.SESS_CACHE_OFF} 0x0, the value of
1845 L{SSL_SESS_CACHE_OFF} defined by I{openssl/ssl.h}.
1846 """
1847 self.assertEqual(0x0, SESS_CACHE_OFF)
1848
1849
1850 def test_sess_cache_client(self):
1851 """
1852 The value of L{OpenSSL.SSL.SESS_CACHE_CLIENT} 0x1, the value of
1853 L{SSL_SESS_CACHE_CLIENT} defined by I{openssl/ssl.h}.
1854 """
1855 self.assertEqual(0x1, SESS_CACHE_CLIENT)
1856
1857
1858 def test_sess_cache_server(self):
1859 """
1860 The value of L{OpenSSL.SSL.SESS_CACHE_SERVER} 0x2, the value of
1861 L{SSL_SESS_CACHE_SERVER} defined by I{openssl/ssl.h}.
1862 """
1863 self.assertEqual(0x2, SESS_CACHE_SERVER)
1864
1865
1866 def test_sess_cache_both(self):
1867 """
1868 The value of L{OpenSSL.SSL.SESS_CACHE_BOTH} 0x3, the value of
1869 L{SSL_SESS_CACHE_BOTH} defined by I{openssl/ssl.h}.
1870 """
1871 self.assertEqual(0x3, SESS_CACHE_BOTH)
1872
1873
1874 def test_sess_cache_no_auto_clear(self):
1875 """
1876 The value of L{OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR} 0x80, the value of
1877 L{SSL_SESS_CACHE_NO_AUTO_CLEAR} defined by I{openssl/ssl.h}.
1878 """
1879 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
1880
1881
1882 def test_sess_cache_no_internal_lookup(self):
1883 """
1884 The value of L{OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP} 0x100, the
1885 value of L{SSL_SESS_CACHE_NO_INTERNAL_LOOKUP} defined by
1886 I{openssl/ssl.h}.
1887 """
1888 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
1889
1890
1891 def test_sess_cache_no_internal_store(self):
1892 """
1893 The value of L{OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE} 0x200, the
1894 value of L{SSL_SESS_CACHE_NO_INTERNAL_STORE} defined by
1895 I{openssl/ssl.h}.
1896 """
1897 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
1898
1899
1900 def test_sess_cache_no_internal(self):
1901 """
1902 The value of L{OpenSSL.SSL.SESS_CACHE_NO_INTERNAL} 0x300, the value of
1903 L{SSL_SESS_CACHE_NO_INTERNAL} defined by I{openssl/ssl.h}.
1904 """
1905 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
1906
1907
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04001908
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001909class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05001910 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001911 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05001912 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001913 def _server(self, sock):
1914 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001915 Create a new server-side SSL :py:obj:`Connection` object wrapped around
1916 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001917 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001918 # Create the server side Connection. This is mostly setup boilerplate
1919 # - use TLSv1, use a particular certificate, etc.
1920 server_ctx = Context(TLSv1_METHOD)
1921 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
1922 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
1923 server_store = server_ctx.get_cert_store()
1924 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1925 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1926 server_ctx.check_privatekey()
1927 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05001928 # Here the Connection is actually created. If None is passed as the 2nd
1929 # parameter, it indicates a memory BIO should be created.
1930 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001931 server_conn.set_accept_state()
1932 return server_conn
1933
1934
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001935 def _client(self, sock):
1936 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001937 Create a new client-side SSL :py:obj:`Connection` object wrapped around
1938 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001939 """
1940 # Now create the client side Connection. Similar boilerplate to the
1941 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001942 client_ctx = Context(TLSv1_METHOD)
1943 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
1944 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
1945 client_store = client_ctx.get_cert_store()
1946 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
1947 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
1948 client_ctx.check_privatekey()
1949 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05001950 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001951 client_conn.set_connect_state()
1952 return client_conn
1953
1954
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001955 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001956 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001957 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001958 reading from the output of each and writing those bytes to the input of
1959 the other and in this way establish a connection and exchange
1960 application-level bytes with each other.
1961 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001962 server_conn = self._server(None)
1963 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05001964
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001965 # There should be no key or nonces yet.
1966 self.assertIdentical(server_conn.master_key(), None)
1967 self.assertIdentical(server_conn.client_random(), None)
1968 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05001969
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001970 # First, the handshake needs to happen. We'll deliver bytes back and
1971 # forth between the client and server until neither of them feels like
1972 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001973 self.assertIdentical(
1974 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001975
1976 # Now that the handshake is done, there should be a key and nonces.
1977 self.assertNotIdentical(server_conn.master_key(), None)
1978 self.assertNotIdentical(server_conn.client_random(), None)
1979 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04001980 self.assertEquals(server_conn.client_random(), client_conn.client_random())
1981 self.assertEquals(server_conn.server_random(), client_conn.server_random())
1982 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
1983 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001984
1985 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04001986 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05001987
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001988 server_conn.write(important_message)
1989 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001990 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001991 (client_conn, important_message))
1992
1993 client_conn.write(important_message[::-1])
1994 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001995 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001996 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05001997
1998
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001999 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05002000 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002001 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002002
2003 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09002004 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002005 this test fails, there must be a problem outside the memory BIO
2006 code, as no memory BIO is involved here). Even though this isn't a
2007 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05002008 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04002009 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05002010
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002011 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05002012 client_conn.send(important_message)
2013 msg = server_conn.recv(1024)
2014 self.assertEqual(msg, important_message)
2015
2016 # Again in the other direction, just for fun.
2017 important_message = important_message[::-1]
2018 server_conn.send(important_message)
2019 msg = client_conn.recv(1024)
2020 self.assertEqual(msg, important_message)
2021
2022
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04002023 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05002024 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002025 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
2026 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05002027 """
2028 context = Context(SSLv3_METHOD)
2029 client = socket()
2030 clientSSL = Connection(context, client)
2031 self.assertRaises( TypeError, clientSSL.bio_read, 100)
2032 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04002033 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002034
2035
2036 def test_outgoingOverflow(self):
2037 """
2038 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002039 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002040 returned and that many bytes from the beginning of the input can be
2041 read from the other end of the connection.
2042 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002043 server = self._server(None)
2044 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002045
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002046 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002047
2048 size = 2 ** 15
2049 sent = client.send("x" * size)
2050 # Sanity check. We're trying to test what happens when the entire
2051 # input can't be sent. If the entire input was sent, this test is
2052 # meaningless.
2053 self.assertTrue(sent < size)
2054
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002055 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002056 self.assertIdentical(receiver, server)
2057
2058 # We can rely on all of these bytes being received at once because
2059 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
2060 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002061
2062
2063 def test_shutdown(self):
2064 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002065 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
2066 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002067 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002068 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002069 server.bio_shutdown()
2070 e = self.assertRaises(Error, server.recv, 1024)
2071 # We don't want WantReadError or ZeroReturnError or anything - it's a
2072 # handshake failure.
2073 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002074
2075
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002076 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002077 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002078 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 -04002079
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002080 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002081 before the client and server are connected to each other. This
2082 function should specify a list of CAs for the server to send to the
2083 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09002084 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002085 times.
2086 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002087 server = self._server(None)
2088 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002089 self.assertEqual(client.get_client_ca_list(), [])
2090 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002091 ctx = server.get_context()
2092 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002093 self.assertEqual(client.get_client_ca_list(), [])
2094 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002095 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002096 self.assertEqual(client.get_client_ca_list(), expected)
2097 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002098
2099
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002100 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002101 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002102 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002103 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002104 """
2105 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002106 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
2107 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
2108 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002109
2110
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002111 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002112 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002113 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002114 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09002115 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002116 after the connection is set up.
2117 """
2118 def no_ca(ctx):
2119 ctx.set_client_ca_list([])
2120 return []
2121 self._check_client_ca_list(no_ca)
2122
2123
2124 def test_set_one_ca_list(self):
2125 """
2126 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002127 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002128 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002129 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002130 X509Name after the connection is set up.
2131 """
2132 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2133 cadesc = cacert.get_subject()
2134 def single_ca(ctx):
2135 ctx.set_client_ca_list([cadesc])
2136 return [cadesc]
2137 self._check_client_ca_list(single_ca)
2138
2139
2140 def test_set_multiple_ca_list(self):
2141 """
2142 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002143 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002144 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002145 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002146 X509Names after the connection is set up.
2147 """
2148 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2149 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2150
2151 sedesc = secert.get_subject()
2152 cldesc = clcert.get_subject()
2153
2154 def multiple_ca(ctx):
2155 L = [sedesc, cldesc]
2156 ctx.set_client_ca_list(L)
2157 return L
2158 self._check_client_ca_list(multiple_ca)
2159
2160
2161 def test_reset_ca_list(self):
2162 """
2163 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09002164 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002165 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002166 """
2167 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2168 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2169 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2170
2171 cadesc = cacert.get_subject()
2172 sedesc = secert.get_subject()
2173 cldesc = clcert.get_subject()
2174
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002175 def changed_ca(ctx):
2176 ctx.set_client_ca_list([sedesc, cldesc])
2177 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002178 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002179 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002180
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002181
2182 def test_mutated_ca_list(self):
2183 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002184 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002185 afterwards, this does not affect the list of CA names sent to the
2186 client.
2187 """
2188 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2189 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2190
2191 cadesc = cacert.get_subject()
2192 sedesc = secert.get_subject()
2193
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002194 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002195 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002196 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002197 L.append(sedesc)
2198 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002199 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002200
2201
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002202 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002203 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002204 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002205 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002206 """
2207 ctx = Context(TLSv1_METHOD)
2208 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002209 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002210 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002211 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002212
2213
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002214 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002215 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002216 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09002217 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002218 """
2219 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2220 cadesc = cacert.get_subject()
2221 def single_ca(ctx):
2222 ctx.add_client_ca(cacert)
2223 return [cadesc]
2224 self._check_client_ca_list(single_ca)
2225
2226
2227 def test_multiple_add_client_ca(self):
2228 """
2229 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09002230 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002231 """
2232 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2233 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2234
2235 cadesc = cacert.get_subject()
2236 sedesc = secert.get_subject()
2237
2238 def multiple_ca(ctx):
2239 ctx.add_client_ca(cacert)
2240 ctx.add_client_ca(secert)
2241 return [cadesc, sedesc]
2242 self._check_client_ca_list(multiple_ca)
2243
2244
2245 def test_set_and_add_client_ca(self):
2246 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002247 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
2248 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002249 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002250 """
2251 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2252 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2253 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2254
2255 cadesc = cacert.get_subject()
2256 sedesc = secert.get_subject()
2257 cldesc = clcert.get_subject()
2258
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002259 def mixed_set_add_ca(ctx):
2260 ctx.set_client_ca_list([cadesc, sedesc])
2261 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002262 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002263 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002264
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002265
2266 def test_set_after_add_client_ca(self):
2267 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002268 A call to :py:obj:`Context.set_client_ca_list` after a call to
2269 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002270 call with the names specified by the latter cal.
2271 """
2272 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2273 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2274 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2275
2276 cadesc = cacert.get_subject()
2277 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002278
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002279 def set_replaces_add_ca(ctx):
2280 ctx.add_client_ca(clcert)
2281 ctx.set_client_ca_list([cadesc])
2282 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002283 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002284 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002285
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002286
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04002287class InfoConstantTests(TestCase):
2288 """
2289 Tests for assorted constants exposed for use in info callbacks.
2290 """
2291 def test_integers(self):
2292 """
2293 All of the info constants are integers.
2294
2295 This is a very weak test. It would be nice to have one that actually
2296 verifies that as certain info events happen, the value passed to the
2297 info callback matches up with the constant exposed by OpenSSL.SSL.
2298 """
2299 for const in [
2300 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
2301 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
2302 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
2303 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
2304 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
2305 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
2306
2307 self.assertTrue(isinstance(const, int))
2308
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02002309
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002310if __name__ == '__main__':
2311 main()