blob: 8100f6e82290e3aa402ca9a3021485803cd86036 [file] [log] [blame]
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05001# Copyright (C) Jean-Paul Calderone
2# See LICENSE for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04003
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04004"""
Jonathan Ballet648875f2011-07-16 14:14:58 +09005Unit tests for :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04006"""
7
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05008from gc import collect, get_referrers
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02009from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE, ESHUTDOWN
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -040010from sys import platform, version_info, getfilesystemencoding
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070011from socket import SHUT_RDWR, error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040012from os import makedirs
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040013from os.path import join
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -040014from unittest import main
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040015from weakref import ref
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050016
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -040017from six import PY3, binary_type, text_type, u
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050018
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040019from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080020from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040021from OpenSSL.crypto import dump_privatekey, load_privatekey
22from OpenSSL.crypto import dump_certificate, load_certificate
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040023from OpenSSL.crypto import get_elliptic_curves
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040024
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040025from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
26from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040027from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040028from OpenSSL.SSL import (
29 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
30 TLSv1_1_METHOD, TLSv1_2_METHOD)
31from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040032from OpenSSL.SSL import (
33 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040034
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040035from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050036 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
37 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
38 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
39
40from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070041 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050042from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070043 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040044
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -040045from OpenSSL.test.util import NON_ASCII, TestCase, b
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040046from OpenSSL.test.test_crypto import (
47 cleartextCertificatePEM, cleartextPrivateKeyPEM)
48from OpenSSL.test.test_crypto import (
49 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
50 root_cert_pem)
51
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050052try:
53 from OpenSSL.SSL import OP_NO_QUERY_MTU
54except ImportError:
55 OP_NO_QUERY_MTU = None
56try:
57 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
58except ImportError:
59 OP_COOKIE_EXCHANGE = None
60try:
61 from OpenSSL.SSL import OP_NO_TICKET
62except ImportError:
63 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040064
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040065try:
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -040066 from OpenSSL.SSL import OP_NO_COMPRESSION
67except ImportError:
68 OP_NO_COMPRESSION = None
69
70try:
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040071 from OpenSSL.SSL import MODE_RELEASE_BUFFERS
72except ImportError:
73 MODE_RELEASE_BUFFERS = None
74
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040075try:
76 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
77except ImportError:
78 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
79
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040080from OpenSSL.SSL import (
81 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
82 SSL_ST_OK, SSL_ST_RENEGOTIATE,
83 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
84 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
85 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
86 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040087
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040088# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
89# to use)
90dhparam = """\
91-----BEGIN DH PARAMETERS-----
92MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
93-----END DH PARAMETERS-----
94"""
95
96
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040097def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040098 return ok
99
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400100
Rick Deanb1ccd562009-07-09 23:52:39 -0500101def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400102 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400103 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400104 """
105 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500106 port = socket()
107 port.bind(('', 0))
108 port.listen(1)
109 client = socket()
110 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400111 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400112 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500113 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500114
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400115 # Let's pass some unencrypted data to make sure our socket connection is
116 # fine. Just one byte, so we don't have to worry about buffers getting
117 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400118 server.send(b("x"))
119 assert client.recv(1024) == b("x")
120 client.send(b("y"))
121 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500122
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400123 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400124 server.setblocking(False)
125 client.setblocking(False)
126
Rick Deanb1ccd562009-07-09 23:52:39 -0500127 return (server, client)
128
129
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400130
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400131def handshake(client, server):
132 conns = [client, server]
133 while conns:
134 for conn in conns:
135 try:
136 conn.do_handshake()
137 except WantReadError:
138 pass
139 else:
140 conns.remove(conn)
141
142
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400143def _create_certificate_chain():
144 """
145 Construct and return a chain of certificates.
146
147 1. A new self-signed certificate authority certificate (cacert)
148 2. A new intermediate certificate signed by cacert (icert)
149 3. A new server certificate signed by icert (scert)
150 """
151 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
152
153 # Step 1
154 cakey = PKey()
155 cakey.generate_key(TYPE_RSA, 512)
156 cacert = X509()
157 cacert.get_subject().commonName = "Authority Certificate"
158 cacert.set_issuer(cacert.get_subject())
159 cacert.set_pubkey(cakey)
160 cacert.set_notBefore(b("20000101000000Z"))
161 cacert.set_notAfter(b("20200101000000Z"))
162 cacert.add_extensions([caext])
163 cacert.set_serial_number(0)
164 cacert.sign(cakey, "sha1")
165
166 # Step 2
167 ikey = PKey()
168 ikey.generate_key(TYPE_RSA, 512)
169 icert = X509()
170 icert.get_subject().commonName = "Intermediate Certificate"
171 icert.set_issuer(cacert.get_subject())
172 icert.set_pubkey(ikey)
173 icert.set_notBefore(b("20000101000000Z"))
174 icert.set_notAfter(b("20200101000000Z"))
175 icert.add_extensions([caext])
176 icert.set_serial_number(0)
177 icert.sign(cakey, "sha1")
178
179 # Step 3
180 skey = PKey()
181 skey.generate_key(TYPE_RSA, 512)
182 scert = X509()
183 scert.get_subject().commonName = "Server Certificate"
184 scert.set_issuer(icert.get_subject())
185 scert.set_pubkey(skey)
186 scert.set_notBefore(b("20000101000000Z"))
187 scert.set_notAfter(b("20200101000000Z"))
188 scert.add_extensions([
189 X509Extension(b('basicConstraints'), True, b('CA:false'))])
190 scert.set_serial_number(0)
191 scert.sign(ikey, "sha1")
192
193 return [(cakey, cacert), (ikey, icert), (skey, scert)]
194
195
196
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400197class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400198 """
199 Helper mixin which defines methods for creating a connected socket pair and
200 for forcing two connected SSL sockets to talk to each other via memory BIOs.
201 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500202 def _loopbackClientFactory(self, socket):
203 client = Connection(Context(TLSv1_METHOD), socket)
204 client.set_connect_state()
205 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400206
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500207
208 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400209 ctx = Context(TLSv1_METHOD)
210 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
211 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500212 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400213 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500214 return server
215
216
217 def _loopback(self, serverFactory=None, clientFactory=None):
218 if serverFactory is None:
219 serverFactory = self._loopbackServerFactory
220 if clientFactory is None:
221 clientFactory = self._loopbackClientFactory
222
223 (server, client) = socket_pair()
224 server = serverFactory(server)
225 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400226
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400227 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400228
229 server.setblocking(True)
230 client.setblocking(True)
231 return server, client
232
233
234 def _interactInMemory(self, client_conn, server_conn):
235 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900236 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400237 objects. Copy bytes back and forth between their send/receive buffers
238 for as long as there is anything to copy. When there is nothing more
Jonathan Ballet648875f2011-07-16 14:14:58 +0900239 to copy, return :py:obj:`None`. If one of them actually manages to deliver
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400240 some application bytes, return a two-tuple of the connection from which
241 the bytes were read and the bytes themselves.
242 """
243 wrote = True
244 while wrote:
245 # Loop until neither side has anything to say
246 wrote = False
247
248 # Copy stuff from each side's send buffer to the other side's
249 # receive buffer.
250 for (read, write) in [(client_conn, server_conn),
251 (server_conn, client_conn)]:
252
253 # Give the side a chance to generate some more bytes, or
254 # succeed.
255 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400256 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400257 except WantReadError:
258 # It didn't succeed, so we'll hope it generated some
259 # output.
260 pass
261 else:
262 # It did succeed, so we'll stop now and let the caller deal
263 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400264 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400265
266 while True:
267 # Keep copying as long as there's more stuff there.
268 try:
269 dirty = read.bio_read(4096)
270 except WantReadError:
271 # Okay, nothing more waiting to be sent. Stop
272 # processing this send buffer.
273 break
274 else:
275 # Keep track of the fact that someone generated some
276 # output.
277 wrote = True
278 write.bio_write(dirty)
279
280
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400281 def _handshakeInMemory(self, client_conn, server_conn):
Jean-Paul Calderoneb2b40782014-05-06 08:47:40 -0400282 """
283 Perform the TLS handshake between two :py:class:`Connection` instances
284 connected to each other via memory BIOs.
285 """
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400286 client_conn.set_connect_state()
287 server_conn.set_accept_state()
288
289 for conn in [client_conn, server_conn]:
290 try:
291 conn.do_handshake()
292 except WantReadError:
293 pass
294
295 self._interactInMemory(client_conn, server_conn)
296
297
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400298
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400299class VersionTests(TestCase):
300 """
301 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900302 :py:obj:`OpenSSL.SSL.SSLeay_version` and
303 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400304 """
305 def test_OPENSSL_VERSION_NUMBER(self):
306 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900307 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400308 byte and the patch, fix, minor, and major versions in the
309 nibbles above that.
310 """
311 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
312
313
314 def test_SSLeay_version(self):
315 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900316 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400317 one of a number of version strings based on that indicator.
318 """
319 versions = {}
320 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
321 SSLEAY_PLATFORM, SSLEAY_DIR]:
322 version = SSLeay_version(t)
323 versions[version] = t
324 self.assertTrue(isinstance(version, bytes))
325 self.assertEqual(len(versions), 5)
326
327
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400328
329class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400330 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900331 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400332 """
333 def test_method(self):
334 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900335 :py:obj:`Context` can be instantiated with one of :py:obj:`SSLv2_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400336 :py:obj:`SSLv3_METHOD`, :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
337 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400338 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400339 methods = [
340 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
341 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400342 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400343
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400344
345 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
346 for meth in maybe:
347 try:
348 Context(meth)
349 except (Error, ValueError):
350 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
351 # don't. Difficult to say in advance.
352 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400353
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400354 self.assertRaises(TypeError, Context, "")
355 self.assertRaises(ValueError, Context, 10)
356
357
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500358 if not PY3:
359 def test_method_long(self):
360 """
361 On Python 2 :py:class:`Context` accepts values of type
362 :py:obj:`long` as well as :py:obj:`int`.
363 """
364 Context(long(TLSv1_METHOD))
365
366
367
Rick Deane15b1472009-07-09 15:53:42 -0500368 def test_type(self):
369 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900370 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400371 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500372 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400373 self.assertIdentical(Context, ContextType)
374 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500375
376
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400377 def test_use_privatekey(self):
378 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900379 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400380 """
381 key = PKey()
382 key.generate_key(TYPE_RSA, 128)
383 ctx = Context(TLSv1_METHOD)
384 ctx.use_privatekey(key)
385 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400386
387
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800388 def test_use_privatekey_file_missing(self):
389 """
390 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error`
391 when passed the name of a file which does not exist.
392 """
393 ctx = Context(TLSv1_METHOD)
394 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
395
396
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400397 def _use_privatekey_file_test(self, pemfile, filetype):
398 """
399 Verify that calling ``Context.use_privatekey_file`` with the given
400 arguments does not raise an exception.
401 """
402 key = PKey()
403 key.generate_key(TYPE_RSA, 128)
404
405 with open(pemfile, "wt") as pem:
406 pem.write(
407 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
408 )
409
410 ctx = Context(TLSv1_METHOD)
411 ctx.use_privatekey_file(pemfile, filetype)
412
413
414 def test_use_privatekey_file_bytes(self):
415 """
416 A private key can be specified from a file by passing a ``bytes``
417 instance giving the file name to ``Context.use_privatekey_file``.
418 """
419 self._use_privatekey_file_test(
420 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
421 FILETYPE_PEM,
422 )
423
424
425 def test_use_privatekey_file_unicode(self):
426 """
427 A private key can be specified from a file by passing a ``unicode``
428 instance giving the file name to ``Context.use_privatekey_file``.
429 """
430 self._use_privatekey_file_test(
431 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
432 FILETYPE_PEM,
433 )
434
435
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500436 if not PY3:
437 def test_use_privatekey_file_long(self):
438 """
439 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
440 filetype of type :py:obj:`long` as well as :py:obj:`int`.
441 """
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400442 self._use_privatekey_file_test(self.mktemp(), long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500443
444
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800445 def test_use_certificate_wrong_args(self):
446 """
447 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
448 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as an
449 argument.
450 """
451 ctx = Context(TLSv1_METHOD)
452 self.assertRaises(TypeError, ctx.use_certificate)
453 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
454 self.assertRaises(TypeError, ctx.use_certificate, X509(), "hello, world")
455
456
457 def test_use_certificate_uninitialized(self):
458 """
459 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
460 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
461 initialized (ie, which does not actually have any certificate data).
462 """
463 ctx = Context(TLSv1_METHOD)
464 self.assertRaises(Error, ctx.use_certificate, X509())
465
466
467 def test_use_certificate(self):
468 """
469 :py:obj:`Context.use_certificate` sets the certificate which will be
470 used to identify connections created using the context.
471 """
472 # TODO
473 # Hard to assert anything. But we could set a privatekey then ask
474 # OpenSSL if the cert and key agree using check_privatekey. Then as
475 # long as check_privatekey works right we're good...
476 ctx = Context(TLSv1_METHOD)
477 ctx.use_certificate(load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
478
479
480 def test_use_certificate_file_wrong_args(self):
481 """
482 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
483 called with zero arguments or more than two arguments, or if the first
484 argument is not a byte string or the second argumnent is not an integer.
485 """
486 ctx = Context(TLSv1_METHOD)
487 self.assertRaises(TypeError, ctx.use_certificate_file)
488 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile", object())
489 self.assertRaises(
490 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM, object())
491 self.assertRaises(
492 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
493 self.assertRaises(
494 TypeError, ctx.use_certificate_file, b"somefile", object())
495
496
497 def test_use_certificate_file_missing(self):
498 """
499 :py:obj:`Context.use_certificate_file` raises
500 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does not
501 exist.
502 """
503 ctx = Context(TLSv1_METHOD)
504 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
505
506
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400507 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800508 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400509 Verify that calling ``Context.use_certificate_file`` with the given
510 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800511 """
512 # TODO
513 # Hard to assert anything. But we could set a privatekey then ask
514 # OpenSSL if the cert and key agree using check_privatekey. Then as
515 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400516 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800517 pem_file.write(cleartextCertificatePEM)
518
519 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400520 ctx.use_certificate_file(certificate_file)
521
522
523 def test_use_certificate_file_bytes(self):
524 """
525 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
526 ``bytes`` filename) which will be used to identify connections created
527 using the context.
528 """
529 filename = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
530 self._use_certificate_file_test(filename)
531
532
533 def test_use_certificate_file_unicode(self):
534 """
535 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
536 ``bytes`` filename) which will be used to identify connections created
537 using the context.
538 """
539 filename = self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
540 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800541
542
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500543 if not PY3:
544 def test_use_certificate_file_long(self):
545 """
546 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
547 filetype of type :py:obj:`long` as well as :py:obj:`int`.
548 """
549 pem_filename = self.mktemp()
550 with open(pem_filename, "wb") as pem_file:
551 pem_file.write(cleartextCertificatePEM)
552
553 ctx = Context(TLSv1_METHOD)
554 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
555
556
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400557 def test_set_app_data_wrong_args(self):
558 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900559 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called with other than
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400560 one argument.
561 """
562 context = Context(TLSv1_METHOD)
563 self.assertRaises(TypeError, context.set_app_data)
564 self.assertRaises(TypeError, context.set_app_data, None, None)
565
566
567 def test_get_app_data_wrong_args(self):
568 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900569 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400570 arguments.
571 """
572 context = Context(TLSv1_METHOD)
573 self.assertRaises(TypeError, context.get_app_data, None)
574
575
576 def test_app_data(self):
577 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900578 :py:obj:`Context.set_app_data` stores an object for later retrieval using
579 :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400580 """
581 app_data = object()
582 context = Context(TLSv1_METHOD)
583 context.set_app_data(app_data)
584 self.assertIdentical(context.get_app_data(), app_data)
585
586
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400587 def test_set_options_wrong_args(self):
588 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900589 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with the wrong
590 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400591 """
592 context = Context(TLSv1_METHOD)
593 self.assertRaises(TypeError, context.set_options)
594 self.assertRaises(TypeError, context.set_options, None)
595 self.assertRaises(TypeError, context.set_options, 1, None)
596
597
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500598 def test_set_options(self):
599 """
600 :py:obj:`Context.set_options` returns the new options value.
601 """
602 context = Context(TLSv1_METHOD)
603 options = context.set_options(OP_NO_SSLv2)
604 self.assertTrue(OP_NO_SSLv2 & options)
605
606
607 if not PY3:
608 def test_set_options_long(self):
609 """
610 On Python 2 :py:obj:`Context.set_options` accepts values of type
611 :py:obj:`long` as well as :py:obj:`int`.
612 """
613 context = Context(TLSv1_METHOD)
614 options = context.set_options(long(OP_NO_SSLv2))
615 self.assertTrue(OP_NO_SSLv2 & options)
616
617
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300618 def test_set_mode_wrong_args(self):
619 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400620 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with the wrong
621 number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300622 """
623 context = Context(TLSv1_METHOD)
624 self.assertRaises(TypeError, context.set_mode)
625 self.assertRaises(TypeError, context.set_mode, None)
626 self.assertRaises(TypeError, context.set_mode, 1, None)
627
628
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400629 if MODE_RELEASE_BUFFERS is not None:
630 def test_set_mode(self):
631 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400632 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the newly
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400633 set mode.
634 """
635 context = Context(TLSv1_METHOD)
636 self.assertTrue(
637 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500638
639 if not PY3:
640 def test_set_mode_long(self):
641 """
642 On Python 2 :py:obj:`Context.set_mode` accepts values of type
643 :py:obj:`long` as well as :py:obj:`int`.
644 """
645 context = Context(TLSv1_METHOD)
646 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
647 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400648 else:
649 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
650
651
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400652 def test_set_timeout_wrong_args(self):
653 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900654 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with the wrong
655 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400656 """
657 context = Context(TLSv1_METHOD)
658 self.assertRaises(TypeError, context.set_timeout)
659 self.assertRaises(TypeError, context.set_timeout, None)
660 self.assertRaises(TypeError, context.set_timeout, 1, None)
661
662
663 def test_get_timeout_wrong_args(self):
664 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900665 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400666 """
667 context = Context(TLSv1_METHOD)
668 self.assertRaises(TypeError, context.get_timeout, None)
669
670
671 def test_timeout(self):
672 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900673 :py:obj:`Context.set_timeout` sets the session timeout for all connections
674 created using the context object. :py:obj:`Context.get_timeout` retrieves this
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400675 value.
676 """
677 context = Context(TLSv1_METHOD)
678 context.set_timeout(1234)
679 self.assertEquals(context.get_timeout(), 1234)
680
681
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500682 if not PY3:
683 def test_timeout_long(self):
684 """
685 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
686 `long` as well as int.
687 """
688 context = Context(TLSv1_METHOD)
689 context.set_timeout(long(1234))
690 self.assertEquals(context.get_timeout(), 1234)
691
692
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400693 def test_set_verify_depth_wrong_args(self):
694 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900695 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called with the wrong
696 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400697 """
698 context = Context(TLSv1_METHOD)
699 self.assertRaises(TypeError, context.set_verify_depth)
700 self.assertRaises(TypeError, context.set_verify_depth, None)
701 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
702
703
704 def test_get_verify_depth_wrong_args(self):
705 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900706 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400707 """
708 context = Context(TLSv1_METHOD)
709 self.assertRaises(TypeError, context.get_verify_depth, None)
710
711
712 def test_verify_depth(self):
713 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900714 :py:obj:`Context.set_verify_depth` sets the number of certificates in a chain
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400715 to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900716 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400717 """
718 context = Context(TLSv1_METHOD)
719 context.set_verify_depth(11)
720 self.assertEquals(context.get_verify_depth(), 11)
721
722
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500723 if not PY3:
724 def test_verify_depth_long(self):
725 """
726 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
727 type `long` as well as int.
728 """
729 context = Context(TLSv1_METHOD)
730 context.set_verify_depth(long(11))
731 self.assertEquals(context.get_verify_depth(), 11)
732
733
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400734 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400735 """
736 Write a new private key out to a new file, encrypted using the given
737 passphrase. Return the path to the new file.
738 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400739 key = PKey()
740 key.generate_key(TYPE_RSA, 128)
741 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400742 fObj = open(pemFile, 'w')
743 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
744 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400745 fObj.close()
746 return pemFile
747
748
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400749 def test_set_passwd_cb_wrong_args(self):
750 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900751 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called with the
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400752 wrong arguments or with a non-callable first argument.
753 """
754 context = Context(TLSv1_METHOD)
755 self.assertRaises(TypeError, context.set_passwd_cb)
756 self.assertRaises(TypeError, context.set_passwd_cb, None)
757 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
758
759
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400760 def test_set_passwd_cb(self):
761 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900762 :py:obj:`Context.set_passwd_cb` accepts a callable which will be invoked when
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400763 a private key is loaded from an encrypted PEM.
764 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400765 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400766 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400767 calledWith = []
768 def passphraseCallback(maxlen, verify, extra):
769 calledWith.append((maxlen, verify, extra))
770 return passphrase
771 context = Context(TLSv1_METHOD)
772 context.set_passwd_cb(passphraseCallback)
773 context.use_privatekey_file(pemFile)
774 self.assertTrue(len(calledWith), 1)
775 self.assertTrue(isinstance(calledWith[0][0], int))
776 self.assertTrue(isinstance(calledWith[0][1], int))
777 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400778
779
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400780 def test_passwd_callback_exception(self):
781 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900782 :py:obj:`Context.use_privatekey_file` propagates any exception raised by the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400783 passphrase callback.
784 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400785 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400786 def passphraseCallback(maxlen, verify, extra):
787 raise RuntimeError("Sorry, I am a fail.")
788
789 context = Context(TLSv1_METHOD)
790 context.set_passwd_cb(passphraseCallback)
791 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
792
793
794 def test_passwd_callback_false(self):
795 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900796 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400797 passphrase callback returns a false value.
798 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400799 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400800 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500801 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400802
803 context = Context(TLSv1_METHOD)
804 context.set_passwd_cb(passphraseCallback)
805 self.assertRaises(Error, context.use_privatekey_file, pemFile)
806
807
808 def test_passwd_callback_non_string(self):
809 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900810 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400811 passphrase callback returns a true non-string value.
812 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400813 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400814 def passphraseCallback(maxlen, verify, extra):
815 return 10
816
817 context = Context(TLSv1_METHOD)
818 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800819 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400820
821
822 def test_passwd_callback_too_long(self):
823 """
824 If the passphrase returned by the passphrase callback returns a string
825 longer than the indicated maximum length, it is truncated.
826 """
827 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400828 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400829 pemFile = self._write_encrypted_pem(passphrase)
830 def passphraseCallback(maxlen, verify, extra):
831 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400832 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400833
834 context = Context(TLSv1_METHOD)
835 context.set_passwd_cb(passphraseCallback)
836 # This shall succeed because the truncated result is the correct
837 # passphrase.
838 context.use_privatekey_file(pemFile)
839
840
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400841 def test_set_info_callback(self):
842 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900843 :py:obj:`Context.set_info_callback` accepts a callable which will be invoked
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400844 when certain information about an SSL connection is available.
845 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500846 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400847
848 clientSSL = Connection(Context(TLSv1_METHOD), client)
849 clientSSL.set_connect_state()
850
851 called = []
852 def info(conn, where, ret):
853 called.append((conn, where, ret))
854 context = Context(TLSv1_METHOD)
855 context.set_info_callback(info)
856 context.use_certificate(
857 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
858 context.use_privatekey(
859 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
860
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400861 serverSSL = Connection(context, server)
862 serverSSL.set_accept_state()
863
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500864 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400865
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500866 # The callback must always be called with a Connection instance as the
867 # first argument. It would probably be better to split this into
868 # separate tests for client and server side info callbacks so we could
869 # assert it is called with the right Connection instance. It would
870 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500871 notConnections = [
872 conn for (conn, where, ret) in called
873 if not isinstance(conn, Connection)]
874 self.assertEqual(
875 [], notConnections,
876 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400877
878
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400879 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400880 """
881 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400882 its :py:obj:`load_verify_locations` method with the given arguments.
883 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400884 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500885 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400886
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400887 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400888 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400889 # Require that the server certificate verify properly or the
890 # connection will fail.
891 clientContext.set_verify(
892 VERIFY_PEER,
893 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
894
895 clientSSL = Connection(clientContext, client)
896 clientSSL.set_connect_state()
897
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400898 serverContext = Context(TLSv1_METHOD)
899 serverContext.use_certificate(
900 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
901 serverContext.use_privatekey(
902 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
903
904 serverSSL = Connection(serverContext, server)
905 serverSSL.set_accept_state()
906
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400907 # Without load_verify_locations above, the handshake
908 # will fail:
909 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
910 # 'certificate verify failed')]
911 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400912
913 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400914 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400915
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500916
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400917 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400918 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400919 Verify that if path to a file containing a certificate is passed to
920 ``Context.load_verify_locations`` for the ``cafile`` parameter, that
921 certificate is used as a trust root for the purposes of verifying
922 connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400923 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400924 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400925 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400926 fObj.close()
927
928 self._load_verify_locations_test(cafile)
929
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400930
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400931 def test_load_verify_bytes_cafile(self):
932 """
933 :py:obj:`Context.load_verify_locations` accepts a file name as a
934 ``bytes`` instance and uses the certificates within for verification
935 purposes.
936 """
937 cafile = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
938 self._load_verify_cafile(cafile)
939
940
941 def test_load_verify_unicode_cafile(self):
942 """
943 :py:obj:`Context.load_verify_locations` accepts a file name as a
944 ``unicode`` instance and uses the certificates within for verification
945 purposes.
946 """
947 cafile = self.mktemp() + NON_ASCII
948 self._load_verify_cafile(cafile)
949
950
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400951 def test_load_verify_invalid_file(self):
952 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900953 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when passed a
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400954 non-existent cafile.
955 """
956 clientContext = Context(TLSv1_METHOD)
957 self.assertRaises(
958 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400959
960
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400961 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400962 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400963 Verify that if path to a directory containing certificate files is
964 passed to ``Context.load_verify_locations`` for the ``capath``
965 parameter, those certificates are used as trust roots for the purposes
966 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400967 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400968 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400969 # Hash values computed manually with c_rehash to avoid depending on
970 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
971 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500972 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400973 cafile = join(capath, name)
974 fObj = open(cafile, 'w')
975 fObj.write(cleartextCertificatePEM.decode('ascii'))
976 fObj.close()
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400977
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400978 self._load_verify_locations_test(None, capath)
979
980
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400981 def test_load_verify_directory_bytes_capath(self):
982 """
983 :py:obj:`Context.load_verify_locations` accepts a directory name as a
984 ``bytes`` instance and uses the certificates within for verification
985 purposes.
986 """
987 self._load_verify_directory_locations_capath(
988 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
989 )
990
991
992 def test_load_verify_directory_unicode_capath(self):
993 """
994 :py:obj:`Context.load_verify_locations` accepts a directory name as a
995 ``unicode`` instance and uses the certificates within for verification
996 purposes.
997 """
998 self._load_verify_directory_locations_capath(self.mktemp() + NON_ASCII)
999
1000
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001001 def test_load_verify_locations_wrong_args(self):
1002 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001003 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if called with
1004 the wrong number of arguments or with non-:py:obj:`str` arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001005 """
1006 context = Context(TLSv1_METHOD)
1007 self.assertRaises(TypeError, context.load_verify_locations)
1008 self.assertRaises(TypeError, context.load_verify_locations, object())
1009 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
1010 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
1011
1012
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001013 if platform == "win32":
1014 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001015 "See LP#404343 and LP#404344."
1016 else:
1017 def test_set_default_verify_paths(self):
1018 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001019 :py:obj:`Context.set_default_verify_paths` causes the platform-specific CA
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001020 certificate locations to be used for verification purposes.
1021 """
1022 # Testing this requires a server with a certificate signed by one of
1023 # the CAs in the platform CA location. Getting one of those costs
1024 # money. Fortunately (or unfortunately, depending on your
1025 # perspective), it's easy to think of a public server on the
1026 # internet which has such a certificate. Connecting to the network
1027 # in a unit test is bad, but it's the only way I can think of to
1028 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001029
Alex Gaynorb586da32014-11-15 09:22:21 -08001030 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
1031 context = Context(TLSv1_METHOD)
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001032 context.set_default_verify_paths()
1033 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02001034 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001035 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001036
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001037 client = socket()
1038 client.connect(('verisign.com', 443))
1039 clientSSL = Connection(context, client)
1040 clientSSL.set_connect_state()
1041 clientSSL.do_handshake()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001042 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001043 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001044
1045
1046 def test_set_default_verify_paths_signature(self):
1047 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001048 :py:obj:`Context.set_default_verify_paths` takes no arguments and raises
1049 :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001050 """
1051 context = Context(TLSv1_METHOD)
1052 self.assertRaises(TypeError, context.set_default_verify_paths, None)
1053 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
1054 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001055
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001056
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001057 def test_add_extra_chain_cert_invalid_cert(self):
1058 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001059 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if called with
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001060 other than one argument or if called with an object which is not an
Jonathan Ballet648875f2011-07-16 14:14:58 +09001061 instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001062 """
1063 context = Context(TLSv1_METHOD)
1064 self.assertRaises(TypeError, context.add_extra_chain_cert)
1065 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
1066 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
1067
1068
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001069 def _handshake_test(self, serverContext, clientContext):
1070 """
1071 Verify that a client and server created with the given contexts can
1072 successfully handshake and communicate.
1073 """
1074 serverSocket, clientSocket = socket_pair()
1075
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001076 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001077 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001078
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001079 client = Connection(clientContext, clientSocket)
1080 client.set_connect_state()
1081
1082 # Make them talk to each other.
1083 # self._interactInMemory(client, server)
1084 for i in range(3):
1085 for s in [client, server]:
1086 try:
1087 s.do_handshake()
1088 except WantReadError:
1089 pass
1090
1091
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001092 def test_set_verify_callback_connection_argument(self):
1093 """
1094 The first argument passed to the verify callback is the
1095 :py:class:`Connection` instance for which verification is taking place.
1096 """
1097 serverContext = Context(TLSv1_METHOD)
1098 serverContext.use_privatekey(
1099 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1100 serverContext.use_certificate(
1101 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1102 serverConnection = Connection(serverContext, None)
1103
1104 class VerifyCallback(object):
1105 def callback(self, connection, *args):
1106 self.connection = connection
1107 return 1
1108
1109 verify = VerifyCallback()
1110 clientContext = Context(TLSv1_METHOD)
1111 clientContext.set_verify(VERIFY_PEER, verify.callback)
1112 clientConnection = Connection(clientContext, None)
1113 clientConnection.set_connect_state()
1114
1115 self._handshakeInMemory(clientConnection, serverConnection)
1116
1117 self.assertIdentical(verify.connection, clientConnection)
1118
1119
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001120 def test_set_verify_callback_exception(self):
1121 """
1122 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1123 exception, verification fails and the exception is propagated to the
1124 caller of :py:obj:`Connection.do_handshake`.
1125 """
1126 serverContext = Context(TLSv1_METHOD)
1127 serverContext.use_privatekey(
1128 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1129 serverContext.use_certificate(
1130 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1131
1132 clientContext = Context(TLSv1_METHOD)
1133 def verify_callback(*args):
1134 raise Exception("silly verify failure")
1135 clientContext.set_verify(VERIFY_PEER, verify_callback)
1136
1137 exc = self.assertRaises(
1138 Exception, self._handshake_test, serverContext, clientContext)
1139 self.assertEqual("silly verify failure", str(exc))
1140
1141
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001142 def test_add_extra_chain_cert(self):
1143 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001144 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509` instance to add to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001145 the certificate chain.
1146
Jonathan Ballet648875f2011-07-16 14:14:58 +09001147 See :py:obj:`_create_certificate_chain` for the details of the certificate
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001148 chain tested.
1149
1150 The chain is tested by starting a server with scert and connecting
1151 to it with a client which trusts cacert and requires verification to
1152 succeed.
1153 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001154 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001155 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1156
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001157 # Dump the CA certificate to a file because that's the only way to load
1158 # it as a trusted CA in the client context.
1159 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001160 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001161 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001162 fObj.close()
1163
1164 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001165 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001166 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001167 fObj.close()
1168
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001169 # Create the server context
1170 serverContext = Context(TLSv1_METHOD)
1171 serverContext.use_privatekey(skey)
1172 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001173 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001174 serverContext.add_extra_chain_cert(icert)
1175
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001176 # Create the client
1177 clientContext = Context(TLSv1_METHOD)
1178 clientContext.set_verify(
1179 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001180 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001181
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001182 # Try it out.
1183 self._handshake_test(serverContext, clientContext)
1184
1185
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001186 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001187 """
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001188 Verify that :py:obj:`Context.use_certificate_chain_file` reads a
1189 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001190
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001191 The chain is tested by starting a server with scert and connecting to
1192 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001193 succeed.
1194 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001195 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001196 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1197
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001198 makedirs(certdir)
1199
1200 if isinstance(certdir, binary_type):
1201 chainFile = join(certdir, b("chain.pem"))
1202 caFile = join(certdir, b("ca.pem"))
1203 else:
1204 chainFile = join(certdir, u"chain.pem")
1205 caFile = join(certdir, u"ca.pem")
1206
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001207 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001208 with open(chainFile, 'wb') as fObj:
1209 # Most specific to least general.
1210 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1211 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1212 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1213
1214 with open(caFile, 'w') as fObj:
1215 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001216
1217 serverContext = Context(TLSv1_METHOD)
1218 serverContext.use_certificate_chain_file(chainFile)
1219 serverContext.use_privatekey(skey)
1220
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001221 clientContext = Context(TLSv1_METHOD)
1222 clientContext.set_verify(
1223 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001224 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001225
1226 self._handshake_test(serverContext, clientContext)
1227
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001228
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001229 def test_use_certificate_chain_file_bytes(self):
1230 """
1231 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1232 an instance of ``bytes``) to specify additional certificates to use to
1233 construct and verify a trust chain.
1234 """
1235 self._use_certificate_chain_file_test(
1236 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
1237 )
1238
1239
1240 def test_use_certificate_chain_file_unicode(self):
1241 """
1242 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1243 an instance of ``unicode``) to specify additional certificates to use
1244 to construct and verify a trust chain.
1245 """
1246 self._use_certificate_chain_file_test(
1247 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
1248 )
1249
1250
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001251 def test_use_certificate_chain_file_wrong_args(self):
1252 """
1253 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1254 if passed zero or more than one argument or when passed a non-byte
1255 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error` when
1256 passed a bad chain file name (for example, the name of a file which does
1257 not exist).
1258 """
1259 context = Context(TLSv1_METHOD)
1260 self.assertRaises(TypeError, context.use_certificate_chain_file)
1261 self.assertRaises(TypeError, context.use_certificate_chain_file, object())
1262 self.assertRaises(TypeError, context.use_certificate_chain_file, b"foo", object())
1263
1264 self.assertRaises(Error, context.use_certificate_chain_file, self.mktemp())
1265
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001266 # XXX load_client_ca
1267 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001268
1269 def test_get_verify_mode_wrong_args(self):
1270 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001271 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001272 arguments.
1273 """
1274 context = Context(TLSv1_METHOD)
1275 self.assertRaises(TypeError, context.get_verify_mode, None)
1276
1277
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001278 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001279 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001280 :py:obj:`Context.get_verify_mode` returns the verify mode flags previously
1281 passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001282 """
1283 context = Context(TLSv1_METHOD)
1284 self.assertEquals(context.get_verify_mode(), 0)
1285 context.set_verify(
1286 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1287 self.assertEquals(
1288 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1289
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001290
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001291 if not PY3:
1292 def test_set_verify_mode_long(self):
1293 """
1294 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1295 type :py:obj:`long` as well as :py:obj:`int`.
1296 """
1297 context = Context(TLSv1_METHOD)
1298 self.assertEquals(context.get_verify_mode(), 0)
1299 context.set_verify(
1300 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None)
1301 self.assertEquals(
1302 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1303
1304
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001305 def test_load_tmp_dh_wrong_args(self):
1306 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001307 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
1308 number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001309 """
1310 context = Context(TLSv1_METHOD)
1311 self.assertRaises(TypeError, context.load_tmp_dh)
1312 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1313 self.assertRaises(TypeError, context.load_tmp_dh, object())
1314
1315
1316 def test_load_tmp_dh_missing_file(self):
1317 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001318 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the specified file
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001319 does not exist.
1320 """
1321 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001322 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001323
1324
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001325 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001326 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001327 with open(dhfilename, "w") as dhfile:
1328 dhfile.write(dhparam)
1329
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001330 context.load_tmp_dh(dhfilename)
1331 # XXX What should I assert here? -exarkun
1332
1333
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001334 def test_load_tmp_dh_bytes(self):
1335 """
1336 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1337 specified file (given as ``bytes``).
1338 """
1339 self._load_tmp_dh_test(
1340 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
1341 )
1342
1343
1344 def test_load_tmp_dh_unicode(self):
1345 """
1346 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1347 specified file (given as ``unicode``).
1348 """
1349 self._load_tmp_dh_test(
1350 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
1351 )
1352
1353
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001354 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001355 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001356 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001357 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001358 """
1359 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001360 for curve in get_elliptic_curves():
1361 # The only easily "assertable" thing is that it does not raise an
1362 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001363 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001364
1365
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001366 def test_set_cipher_list_bytes(self):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001367 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001368 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
1369 ciphers which connections created with the context object will be able
1370 to choose from.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001371 """
1372 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001373 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001374 conn = Connection(context, None)
1375 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001376
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001377
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001378 def test_set_cipher_list_text(self):
1379 """
1380 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
1381 the ciphers which connections created with the context object will be
1382 able to choose from.
1383 """
1384 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -05001385 context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001386 conn = Connection(context, None)
1387 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
1388
1389
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001390 def test_set_cipher_list_wrong_args(self):
1391 """
Jean-Paul Calderone17044832014-01-18 10:20:11 -05001392 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
1393 passed zero arguments or more than one argument or when passed a
1394 non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001395 passed an incorrect cipher list string.
1396 """
1397 context = Context(TLSv1_METHOD)
1398 self.assertRaises(TypeError, context.set_cipher_list)
1399 self.assertRaises(TypeError, context.set_cipher_list, object())
1400 self.assertRaises(TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object())
1401
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001402 self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001403
1404
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001405 def test_set_session_cache_mode_wrong_args(self):
1406 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001407 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1408 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001409 """
1410 context = Context(TLSv1_METHOD)
1411 self.assertRaises(TypeError, context.set_session_cache_mode)
1412 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1413
1414
1415 def test_get_session_cache_mode_wrong_args(self):
1416 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001417 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1418 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001419 """
1420 context = Context(TLSv1_METHOD)
1421 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1422
1423
1424 def test_session_cache_mode(self):
1425 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001426 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1427 cached. The setting can be retrieved via
1428 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001429 """
1430 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001431 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001432 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1433 self.assertEqual(SESS_CACHE_OFF, off)
1434 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1435
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001436 if not PY3:
1437 def test_session_cache_mode_long(self):
1438 """
1439 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1440 of type :py:obj:`long` as well as :py:obj:`int`.
1441 """
1442 context = Context(TLSv1_METHOD)
1443 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1444 self.assertEqual(
1445 SESS_CACHE_BOTH, context.get_session_cache_mode())
1446
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001447
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001448 def test_get_cert_store(self):
1449 """
1450 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store` instance.
1451 """
1452 context = Context(TLSv1_METHOD)
1453 store = context.get_cert_store()
1454 self.assertIsInstance(store, X509Store)
1455
1456
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001457
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001458class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1459 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001460 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
1461 :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001462 """
1463 def test_wrong_args(self):
1464 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001465 :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001466 with other than one argument.
1467 """
1468 context = Context(TLSv1_METHOD)
1469 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1470 self.assertRaises(
1471 TypeError, context.set_tlsext_servername_callback, 1, 2)
1472
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001473
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001474 def test_old_callback_forgotten(self):
1475 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001476 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001477 callback, the one it replaces is dereferenced.
1478 """
1479 def callback(connection):
1480 pass
1481
1482 def replacement(connection):
1483 pass
1484
1485 context = Context(TLSv1_METHOD)
1486 context.set_tlsext_servername_callback(callback)
1487
1488 tracker = ref(callback)
1489 del callback
1490
1491 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001492
1493 # One run of the garbage collector happens to work on CPython. PyPy
1494 # doesn't collect the underlying object until a second run for whatever
1495 # reason. That's fine, it still demonstrates our code has properly
1496 # dropped the reference.
1497 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001498 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001499
1500 callback = tracker()
1501 if callback is not None:
1502 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001503 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001504 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001505
1506
1507 def test_no_servername(self):
1508 """
1509 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001510 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
1511 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001512 """
1513 args = []
1514 def servername(conn):
1515 args.append((conn, conn.get_servername()))
1516 context = Context(TLSv1_METHOD)
1517 context.set_tlsext_servername_callback(servername)
1518
1519 # Lose our reference to it. The Context is responsible for keeping it
1520 # alive now.
1521 del servername
1522 collect()
1523
1524 # Necessary to actually accept the connection
1525 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1526 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1527
1528 # Do a little connection to trigger the logic
1529 server = Connection(context, None)
1530 server.set_accept_state()
1531
1532 client = Connection(Context(TLSv1_METHOD), None)
1533 client.set_connect_state()
1534
1535 self._interactInMemory(server, client)
1536
1537 self.assertEqual([(server, None)], args)
1538
1539
1540 def test_servername(self):
1541 """
1542 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +09001543 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
1544 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001545 """
1546 args = []
1547 def servername(conn):
1548 args.append((conn, conn.get_servername()))
1549 context = Context(TLSv1_METHOD)
1550 context.set_tlsext_servername_callback(servername)
1551
1552 # Necessary to actually accept the connection
1553 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1554 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1555
1556 # Do a little connection to trigger the logic
1557 server = Connection(context, None)
1558 server.set_accept_state()
1559
1560 client = Connection(Context(TLSv1_METHOD), None)
1561 client.set_connect_state()
1562 client.set_tlsext_host_name(b("foo1.example.com"))
1563
1564 self._interactInMemory(server, client)
1565
1566 self.assertEqual([(server, b("foo1.example.com"))], args)
1567
1568
1569
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001570class SessionTests(TestCase):
1571 """
1572 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1573 """
1574 def test_construction(self):
1575 """
1576 :py:class:`Session` can be constructed with no arguments, creating a new
1577 instance of that type.
1578 """
1579 new_session = Session()
1580 self.assertTrue(isinstance(new_session, Session))
1581
1582
1583 def test_construction_wrong_args(self):
1584 """
1585 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
1586 is raised.
1587 """
1588 self.assertRaises(TypeError, Session, 123)
1589 self.assertRaises(TypeError, Session, "hello")
1590 self.assertRaises(TypeError, Session, object())
1591
1592
1593
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001594class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05001595 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001596 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001597 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001598 # XXX get_peer_certificate -> None
1599 # XXX sock_shutdown
1600 # XXX master_key -> TypeError
1601 # XXX server_random -> TypeError
1602 # XXX state_string
1603 # XXX connect -> TypeError
1604 # XXX connect_ex -> TypeError
1605 # XXX set_connect_state -> TypeError
1606 # XXX set_accept_state -> TypeError
1607 # XXX renegotiate_pending
1608 # XXX do_handshake -> TypeError
1609 # XXX bio_read -> TypeError
1610 # XXX recv -> TypeError
1611 # XXX send -> TypeError
1612 # XXX bio_write -> TypeError
1613
Rick Deane15b1472009-07-09 15:53:42 -05001614 def test_type(self):
1615 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001616 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001617 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05001618 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001619 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05001620 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001621 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05001622
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001623
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001624 def test_get_context(self):
1625 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001626 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
1627 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001628 """
1629 context = Context(TLSv1_METHOD)
1630 connection = Connection(context, None)
1631 self.assertIdentical(connection.get_context(), context)
1632
1633
1634 def test_get_context_wrong_args(self):
1635 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001636 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001637 arguments.
1638 """
1639 connection = Connection(Context(TLSv1_METHOD), None)
1640 self.assertRaises(TypeError, connection.get_context, None)
1641
1642
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001643 def test_set_context_wrong_args(self):
1644 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001645 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
1646 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001647 than 1.
1648 """
1649 ctx = Context(TLSv1_METHOD)
1650 connection = Connection(ctx, None)
1651 self.assertRaises(TypeError, connection.set_context)
1652 self.assertRaises(TypeError, connection.set_context, object())
1653 self.assertRaises(TypeError, connection.set_context, "hello")
1654 self.assertRaises(TypeError, connection.set_context, 1)
1655 self.assertRaises(TypeError, connection.set_context, 1, 2)
1656 self.assertRaises(
1657 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
1658 self.assertIdentical(ctx, connection.get_context())
1659
1660
1661 def test_set_context(self):
1662 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001663 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001664 for the connection.
1665 """
1666 original = Context(SSLv23_METHOD)
1667 replacement = Context(TLSv1_METHOD)
1668 connection = Connection(original, None)
1669 connection.set_context(replacement)
1670 self.assertIdentical(replacement, connection.get_context())
1671 # Lose our references to the contexts, just in case the Connection isn't
1672 # properly managing its own contributions to their reference counts.
1673 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001674 collect()
1675
1676
1677 def test_set_tlsext_host_name_wrong_args(self):
1678 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001679 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001680 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09001681 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001682 """
1683 conn = Connection(Context(TLSv1_METHOD), None)
1684 self.assertRaises(TypeError, conn.set_tlsext_host_name)
1685 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
1686 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
1687 self.assertRaises(
1688 TypeError, conn.set_tlsext_host_name, b("with\0null"))
1689
1690 if version_info >= (3,):
1691 # On Python 3.x, don't accidentally implicitly convert from text.
1692 self.assertRaises(
1693 TypeError,
1694 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001695
1696
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001697 def test_get_servername_wrong_args(self):
1698 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001699 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001700 arguments.
1701 """
1702 connection = Connection(Context(TLSv1_METHOD), None)
1703 self.assertRaises(TypeError, connection.get_servername, object())
1704 self.assertRaises(TypeError, connection.get_servername, 1)
1705 self.assertRaises(TypeError, connection.get_servername, "hello")
1706
1707
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001708 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001709 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001710 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001711 immediate read.
1712 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001713 connection = Connection(Context(TLSv1_METHOD), None)
1714 self.assertEquals(connection.pending(), 0)
1715
1716
1717 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001718 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001719 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001720 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001721 connection = Connection(Context(TLSv1_METHOD), None)
1722 self.assertRaises(TypeError, connection.pending, None)
1723
1724
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001725 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001726 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001727 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001728 argument or with the wrong number of arguments.
1729 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001730 connection = Connection(Context(TLSv1_METHOD), socket())
1731 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001732 self.assertRaises(TypeError, connection.connect)
1733 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001734
1735
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001736 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001737 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001738 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001739 connect method raises it.
1740 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001741 client = socket()
1742 context = Context(TLSv1_METHOD)
1743 clientSSL = Connection(context, client)
1744 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04001745 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001746
1747
1748 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001749 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001750 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001751 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001752 port = socket()
1753 port.bind(('', 0))
1754 port.listen(3)
1755
1756 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001757 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
1758 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001759
1760
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001761 if platform == "darwin":
1762 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
1763 else:
1764 def test_connect_ex(self):
1765 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001766 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001767 errno instead of raising an exception.
1768 """
1769 port = socket()
1770 port.bind(('', 0))
1771 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001772
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001773 clientSSL = Connection(Context(TLSv1_METHOD), socket())
1774 clientSSL.setblocking(False)
1775 result = clientSSL.connect_ex(port.getsockname())
1776 expected = (EINPROGRESS, EWOULDBLOCK)
1777 self.assertTrue(
1778 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001779
1780
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001781 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001782 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001783 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001784 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001785 connection = Connection(Context(TLSv1_METHOD), socket())
1786 self.assertRaises(TypeError, connection.accept, None)
1787
1788
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001789 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001790 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001791 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
1792 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001793 connection originated from.
1794 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001795 ctx = Context(TLSv1_METHOD)
1796 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1797 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001798 port = socket()
1799 portSSL = Connection(ctx, port)
1800 portSSL.bind(('', 0))
1801 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001802
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001803 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001804
1805 # Calling portSSL.getsockname() here to get the server IP address sounds
1806 # great, but frequently fails on Windows.
1807 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001808
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001809 serverSSL, address = portSSL.accept()
1810
1811 self.assertTrue(isinstance(serverSSL, Connection))
1812 self.assertIdentical(serverSSL.get_context(), ctx)
1813 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001814
1815
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001816 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001817 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001818 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001819 number of arguments or with arguments other than integers.
1820 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001821 connection = Connection(Context(TLSv1_METHOD), None)
1822 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04001823 self.assertRaises(TypeError, connection.get_shutdown, None)
1824 self.assertRaises(TypeError, connection.set_shutdown)
1825 self.assertRaises(TypeError, connection.set_shutdown, None)
1826 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001827
1828
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001829 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001830 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001831 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001832 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001833 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001834 self.assertFalse(server.shutdown())
1835 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001836 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001837 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
1838 client.shutdown()
1839 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
1840 self.assertRaises(ZeroReturnError, server.recv, 1024)
1841 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001842
1843
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001844 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001845 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001846 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001847 process.
1848 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001849 connection = Connection(Context(TLSv1_METHOD), socket())
1850 connection.set_shutdown(RECEIVED_SHUTDOWN)
1851 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1852
1853
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05001854 if not PY3:
1855 def test_set_shutdown_long(self):
1856 """
1857 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
1858 of type :py:obj:`long` as well as :py:obj:`int`.
1859 """
1860 connection = Connection(Context(TLSv1_METHOD), socket())
1861 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
1862 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1863
1864
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001865 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001866 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001867 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
1868 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001869 with any arguments.
1870 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001871 conn = Connection(Context(TLSv1_METHOD), None)
1872 self.assertRaises(TypeError, conn.get_app_data, None)
1873 self.assertRaises(TypeError, conn.set_app_data)
1874 self.assertRaises(TypeError, conn.set_app_data, None, None)
1875
1876
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001877 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001878 """
1879 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001880 :py:obj:`Connection.set_app_data` and later retrieved with
1881 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001882 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001883 conn = Connection(Context(TLSv1_METHOD), None)
1884 app_data = object()
1885 conn.set_app_data(app_data)
1886 self.assertIdentical(conn.get_app_data(), app_data)
1887
1888
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001889 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001890 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001891 :py:obj:`Connection.makefile` is not implemented and calling that method raises
1892 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001893 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001894 conn = Connection(Context(TLSv1_METHOD), None)
1895 self.assertRaises(NotImplementedError, conn.makefile)
1896
1897
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001898 def test_get_peer_cert_chain_wrong_args(self):
1899 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001900 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001901 arguments.
1902 """
1903 conn = Connection(Context(TLSv1_METHOD), None)
1904 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
1905 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
1906 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
1907 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
1908
1909
1910 def test_get_peer_cert_chain(self):
1911 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001912 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001913 the connected server returned for the certification verification.
1914 """
1915 chain = _create_certificate_chain()
1916 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1917
1918 serverContext = Context(TLSv1_METHOD)
1919 serverContext.use_privatekey(skey)
1920 serverContext.use_certificate(scert)
1921 serverContext.add_extra_chain_cert(icert)
1922 serverContext.add_extra_chain_cert(cacert)
1923 server = Connection(serverContext, None)
1924 server.set_accept_state()
1925
1926 # Create the client
1927 clientContext = Context(TLSv1_METHOD)
1928 clientContext.set_verify(VERIFY_NONE, verify_cb)
1929 client = Connection(clientContext, None)
1930 client.set_connect_state()
1931
1932 self._interactInMemory(client, server)
1933
1934 chain = client.get_peer_cert_chain()
1935 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001936 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001937 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001938 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001939 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001940 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001941 "Authority Certificate", chain[2].get_subject().CN)
1942
1943
1944 def test_get_peer_cert_chain_none(self):
1945 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001946 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001947 certificate chain.
1948 """
1949 ctx = Context(TLSv1_METHOD)
1950 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1951 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1952 server = Connection(ctx, None)
1953 server.set_accept_state()
1954 client = Connection(Context(TLSv1_METHOD), None)
1955 client.set_connect_state()
1956 self._interactInMemory(client, server)
1957 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001958
1959
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001960 def test_get_session_wrong_args(self):
1961 """
1962 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
1963 with any arguments.
1964 """
1965 ctx = Context(TLSv1_METHOD)
1966 server = Connection(ctx, None)
1967 self.assertRaises(TypeError, server.get_session, 123)
1968 self.assertRaises(TypeError, server.get_session, "hello")
1969 self.assertRaises(TypeError, server.get_session, object())
1970
1971
1972 def test_get_session_unconnected(self):
1973 """
1974 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
1975 an object which has not been connected.
1976 """
1977 ctx = Context(TLSv1_METHOD)
1978 server = Connection(ctx, None)
1979 session = server.get_session()
1980 self.assertIdentical(None, session)
1981
1982
1983 def test_server_get_session(self):
1984 """
1985 On the server side of a connection, :py:obj:`Connection.get_session`
1986 returns a :py:class:`Session` instance representing the SSL session for
1987 that connection.
1988 """
1989 server, client = self._loopback()
1990 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001991 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001992
1993
1994 def test_client_get_session(self):
1995 """
1996 On the client side of a connection, :py:obj:`Connection.get_session`
1997 returns a :py:class:`Session` instance representing the SSL session for
1998 that connection.
1999 """
2000 server, client = self._loopback()
2001 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002002 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002003
2004
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002005 def test_set_session_wrong_args(self):
2006 """
2007 If called with an object that is not an instance of :py:class:`Session`,
2008 or with other than one argument, :py:obj:`Connection.set_session` raises
2009 :py:obj:`TypeError`.
2010 """
2011 ctx = Context(TLSv1_METHOD)
2012 connection = Connection(ctx, None)
2013 self.assertRaises(TypeError, connection.set_session)
2014 self.assertRaises(TypeError, connection.set_session, 123)
2015 self.assertRaises(TypeError, connection.set_session, "hello")
2016 self.assertRaises(TypeError, connection.set_session, object())
2017 self.assertRaises(
2018 TypeError, connection.set_session, Session(), Session())
2019
2020
2021 def test_client_set_session(self):
2022 """
2023 :py:obj:`Connection.set_session`, when used prior to a connection being
2024 established, accepts a :py:class:`Session` instance and causes an
2025 attempt to re-use the session it represents when the SSL handshake is
2026 performed.
2027 """
2028 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2029 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2030 ctx = Context(TLSv1_METHOD)
2031 ctx.use_privatekey(key)
2032 ctx.use_certificate(cert)
2033 ctx.set_session_id("unity-test")
2034
2035 def makeServer(socket):
2036 server = Connection(ctx, socket)
2037 server.set_accept_state()
2038 return server
2039
2040 originalServer, originalClient = self._loopback(
2041 serverFactory=makeServer)
2042 originalSession = originalClient.get_session()
2043
2044 def makeClient(socket):
2045 client = self._loopbackClientFactory(socket)
2046 client.set_session(originalSession)
2047 return client
2048 resumedServer, resumedClient = self._loopback(
2049 serverFactory=makeServer,
2050 clientFactory=makeClient)
2051
2052 # This is a proxy: in general, we have no access to any unique
2053 # identifier for the session (new enough versions of OpenSSL expose a
2054 # hash which could be usable, but "new enough" is very, very new).
2055 # Instead, exploit the fact that the master key is re-used if the
2056 # session is re-used. As long as the master key for the two connections
2057 # is the same, the session was re-used!
2058 self.assertEqual(
2059 originalServer.master_key(), resumedServer.master_key())
2060
2061
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002062 def test_set_session_wrong_method(self):
2063 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002064 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
2065 instance associated with a context using a different SSL method than the
2066 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
2067 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002068 """
2069 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2070 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2071 ctx = Context(TLSv1_METHOD)
2072 ctx.use_privatekey(key)
2073 ctx.use_certificate(cert)
2074 ctx.set_session_id("unity-test")
2075
2076 def makeServer(socket):
2077 server = Connection(ctx, socket)
2078 server.set_accept_state()
2079 return server
2080
2081 originalServer, originalClient = self._loopback(
2082 serverFactory=makeServer)
2083 originalSession = originalClient.get_session()
2084
2085 def makeClient(socket):
2086 # Intentionally use a different, incompatible method here.
2087 client = Connection(Context(SSLv3_METHOD), socket)
2088 client.set_connect_state()
2089 client.set_session(originalSession)
2090 return client
2091
2092 self.assertRaises(
2093 Error,
2094 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2095
2096
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002097 def test_wantWriteError(self):
2098 """
2099 :py:obj:`Connection` methods which generate output raise
2100 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2101 fail indicating a should-write state.
2102 """
2103 client_socket, server_socket = socket_pair()
2104 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002105 # anything. Only write a single byte at a time so we can be sure we
2106 # completely fill the buffer. Even though the socket API is allowed to
2107 # signal a short write via its return value it seems this doesn't
2108 # always happen on all platforms (FreeBSD and OS X particular) for the
2109 # very last bit of available buffer space.
2110 msg = b"x"
2111 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002112 try:
2113 client_socket.send(msg)
2114 except error as e:
2115 if e.errno == EWOULDBLOCK:
2116 break
2117 raise
2118 else:
2119 self.fail(
2120 "Failed to fill socket buffer, cannot test BIO want write")
2121
2122 ctx = Context(TLSv1_METHOD)
2123 conn = Connection(ctx, client_socket)
2124 # Client's speak first, so make it an SSL client
2125 conn.set_connect_state()
2126 self.assertRaises(WantWriteError, conn.do_handshake)
2127
2128 # XXX want_read
2129
Fedor Brunner416f4a12014-03-28 13:18:38 +01002130 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002131 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002132 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2133 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002134 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002135 ctx = Context(TLSv1_METHOD)
2136 connection = Connection(ctx, None)
2137 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002138
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002139
Fedor Brunner416f4a12014-03-28 13:18:38 +01002140 def test_get_peer_finished_before_connect(self):
2141 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002142 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2143 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002144 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002145 ctx = Context(TLSv1_METHOD)
2146 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002147 self.assertEqual(connection.get_peer_finished(), None)
2148
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002149
Fedor Brunner416f4a12014-03-28 13:18:38 +01002150 def test_get_finished(self):
2151 """
2152 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002153 message send from client, or server. Finished messages are send during
2154 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002155 """
2156
Fedor Brunner5747b932014-03-05 14:22:34 +01002157 server, client = self._loopback()
2158
2159 self.assertNotEqual(server.get_finished(), None)
2160 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002161
Jean-Paul Calderoned979f232014-03-30 11:58:00 -04002162
Fedor Brunner416f4a12014-03-28 13:18:38 +01002163 def test_get_peer_finished(self):
2164 """
2165 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002166 message received from client, or server. Finished messages are send
2167 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002168 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002169 server, client = self._loopback()
2170
2171 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002172 self.assertTrue(len(server.get_peer_finished()) > 0)
2173
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002174
Fedor Brunner416f4a12014-03-28 13:18:38 +01002175 def test_tls_finished_message_symmetry(self):
2176 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002177 The TLS Finished message send by server must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002178 received by client.
2179
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002180 The TLS Finished message send by client must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002181 received by server.
2182 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002183 server, client = self._loopback()
2184
Fedor Brunner5747b932014-03-05 14:22:34 +01002185 self.assertEqual(server.get_finished(), client.get_peer_finished())
2186 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002187
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002188
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002189 def test_get_cipher_name_before_connect(self):
2190 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002191 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2192 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002193 """
2194 ctx = Context(TLSv1_METHOD)
2195 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002196 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002197
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002198
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002199 def test_get_cipher_name(self):
2200 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002201 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2202 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002203 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002204 server, client = self._loopback()
2205 server_cipher_name, client_cipher_name = \
2206 server.get_cipher_name(), client.get_cipher_name()
2207
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002208 self.assertIsInstance(server_cipher_name, text_type)
2209 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002210
2211 self.assertEqual(server_cipher_name, client_cipher_name)
2212
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002213
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002214 def test_get_cipher_version_before_connect(self):
2215 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002216 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2217 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002218 """
2219 ctx = Context(TLSv1_METHOD)
2220 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002221 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002222
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002223
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002224 def test_get_cipher_version(self):
2225 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002226 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2227 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002228 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002229 server, client = self._loopback()
2230 server_cipher_version, client_cipher_version = \
2231 server.get_cipher_version(), client.get_cipher_version()
2232
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002233 self.assertIsInstance(server_cipher_version, text_type)
2234 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002235
2236 self.assertEqual(server_cipher_version, client_cipher_version)
2237
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002238
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002239 def test_get_cipher_bits_before_connect(self):
2240 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002241 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2242 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002243 """
2244 ctx = Context(TLSv1_METHOD)
2245 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002246 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002247
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002248
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002249 def test_get_cipher_bits(self):
2250 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002251 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2252 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002253 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002254 server, client = self._loopback()
2255 server_cipher_bits, client_cipher_bits = \
2256 server.get_cipher_bits(), client.get_cipher_bits()
2257
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002258 self.assertIsInstance(server_cipher_bits, int)
2259 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002260
2261 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002262
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002263
2264
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002265class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002266 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002267 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002268 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002269 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002270 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002271 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002272 arguments.
2273 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002274 connection = Connection(Context(TLSv1_METHOD), None)
2275 self.assertRaises(TypeError, connection.get_cipher_list, None)
2276
2277
2278 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002279 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002280 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2281 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002282 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002283 connection = Connection(Context(TLSv1_METHOD), None)
2284 ciphers = connection.get_cipher_list()
2285 self.assertTrue(isinstance(ciphers, list))
2286 for cipher in ciphers:
2287 self.assertTrue(isinstance(cipher, str))
2288
2289
2290
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002291class ConnectionSendTests(TestCase, _LoopbackMixin):
2292 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002293 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002294 """
2295 def test_wrong_args(self):
2296 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002297 When called with arguments other than string argument for its first
2298 parameter or more than two arguments, :py:obj:`Connection.send` raises
2299 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002300 """
2301 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002302 self.assertRaises(TypeError, connection.send)
2303 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002304 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002305
2306
2307 def test_short_bytes(self):
2308 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002309 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002310 and returns the number of bytes sent.
2311 """
2312 server, client = self._loopback()
2313 count = server.send(b('xy'))
2314 self.assertEquals(count, 2)
2315 self.assertEquals(client.recv(2), b('xy'))
2316
2317 try:
2318 memoryview
2319 except NameError:
2320 "cannot test sending memoryview without memoryview"
2321 else:
2322 def test_short_memoryview(self):
2323 """
2324 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002325 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002326 bytes sent.
2327 """
2328 server, client = self._loopback()
2329 count = server.send(memoryview(b('xy')))
2330 self.assertEquals(count, 2)
2331 self.assertEquals(client.recv(2), b('xy'))
2332
2333
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002334 try:
2335 buffer
2336 except NameError:
2337 "cannot test sending buffer without buffer"
2338 else:
2339 def test_short_buffer(self):
2340 """
2341 When passed a buffer containing a small number of bytes,
2342 :py:obj:`Connection.send` transmits all of them and returns the number of
2343 bytes sent.
2344 """
2345 server, client = self._loopback()
2346 count = server.send(buffer(b('xy')))
2347 self.assertEquals(count, 2)
2348 self.assertEquals(client.recv(2), b('xy'))
2349
2350
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002351
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002352class ConnectionSendallTests(TestCase, _LoopbackMixin):
2353 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002354 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002355 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002356 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002357 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002358 When called with arguments other than a string argument for its first
2359 parameter or with more than two arguments, :py:obj:`Connection.sendall`
2360 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002361 """
2362 connection = Connection(Context(TLSv1_METHOD), None)
2363 self.assertRaises(TypeError, connection.sendall)
2364 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002365 self.assertRaises(
2366 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002367
2368
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002369 def test_short(self):
2370 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002371 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002372 it.
2373 """
2374 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04002375 server.sendall(b('x'))
2376 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002377
2378
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002379 try:
2380 memoryview
2381 except NameError:
2382 "cannot test sending memoryview without memoryview"
2383 else:
2384 def test_short_memoryview(self):
2385 """
2386 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002387 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002388 """
2389 server, client = self._loopback()
2390 server.sendall(memoryview(b('x')))
2391 self.assertEquals(client.recv(1), b('x'))
2392
2393
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002394 try:
2395 buffer
2396 except NameError:
2397 "cannot test sending buffers without buffers"
2398 else:
2399 def test_short_buffers(self):
2400 """
2401 When passed a buffer containing a small number of bytes,
2402 :py:obj:`Connection.sendall` transmits all of them.
2403 """
2404 server, client = self._loopback()
2405 server.sendall(buffer(b('x')))
2406 self.assertEquals(client.recv(1), b('x'))
2407
2408
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002409 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002410 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002411 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002412 it even if this requires multiple calls of an underlying write function.
2413 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002414 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04002415 # Should be enough, underlying SSL_write should only do 16k at a time.
2416 # On Windows, after 32k of bytes the write will block (forever - because
2417 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04002418 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002419 server.sendall(message)
2420 accum = []
2421 received = 0
2422 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04002423 data = client.recv(1024)
2424 accum.append(data)
2425 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04002426 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002427
2428
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002429 def test_closed(self):
2430 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002431 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002432 write error from the low level write call.
2433 """
2434 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04002435 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002436 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02002437 if platform == "win32":
2438 self.assertEqual(exc.args[0], ESHUTDOWN)
2439 else:
2440 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002441
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002442
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002443
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002444class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
2445 """
2446 Tests for SSL renegotiation APIs.
2447 """
2448 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002449 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002450 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002451 arguments.
2452 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002453 connection = Connection(Context(TLSv1_METHOD), None)
2454 self.assertRaises(TypeError, connection.renegotiate, None)
2455
2456
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002457 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002458 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002459 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002460 any arguments.
2461 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002462 connection = Connection(Context(TLSv1_METHOD), None)
2463 self.assertRaises(TypeError, connection.total_renegotiations, None)
2464
2465
2466 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002467 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002468 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002469 renegotiations have happened.
2470 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002471 connection = Connection(Context(TLSv1_METHOD), None)
2472 self.assertEquals(connection.total_renegotiations(), 0)
2473
2474
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002475# def test_renegotiate(self):
2476# """
2477# """
2478# server, client = self._loopback()
2479
2480# server.send("hello world")
2481# self.assertEquals(client.recv(len("hello world")), "hello world")
2482
2483# self.assertEquals(server.total_renegotiations(), 0)
2484# self.assertTrue(server.renegotiate())
2485
2486# server.setblocking(False)
2487# client.setblocking(False)
2488# while server.renegotiate_pending():
2489# client.do_handshake()
2490# server.do_handshake()
2491
2492# self.assertEquals(server.total_renegotiations(), 1)
2493
2494
2495
2496
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002497class ErrorTests(TestCase):
2498 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002499 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002500 """
2501 def test_type(self):
2502 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002503 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002504 """
2505 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05002506 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05002507
2508
2509
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002510class ConstantsTests(TestCase):
2511 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002512 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002513
2514 These are values defined by OpenSSL intended only to be used as flags to
2515 OpenSSL APIs. The only assertions it seems can be made about them is
2516 their values.
2517 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002518 # unittest.TestCase has no skip mechanism
2519 if OP_NO_QUERY_MTU is not None:
2520 def test_op_no_query_mtu(self):
2521 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002522 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002523 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002524 """
2525 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
2526 else:
2527 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002528
2529
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002530 if OP_COOKIE_EXCHANGE is not None:
2531 def test_op_cookie_exchange(self):
2532 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002533 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002534 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002535 """
2536 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
2537 else:
2538 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002539
2540
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002541 if OP_NO_TICKET is not None:
2542 def test_op_no_ticket(self):
2543 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002544 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002545 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002546 """
2547 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04002548 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002549 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05002550
2551
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002552 if OP_NO_COMPRESSION is not None:
2553 def test_op_no_compression(self):
2554 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002555 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
2556 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002557 """
2558 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
2559 else:
2560 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
2561
2562
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002563 def test_sess_cache_off(self):
2564 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002565 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
2566 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002567 """
2568 self.assertEqual(0x0, SESS_CACHE_OFF)
2569
2570
2571 def test_sess_cache_client(self):
2572 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002573 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
2574 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002575 """
2576 self.assertEqual(0x1, SESS_CACHE_CLIENT)
2577
2578
2579 def test_sess_cache_server(self):
2580 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002581 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
2582 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002583 """
2584 self.assertEqual(0x2, SESS_CACHE_SERVER)
2585
2586
2587 def test_sess_cache_both(self):
2588 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002589 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
2590 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002591 """
2592 self.assertEqual(0x3, SESS_CACHE_BOTH)
2593
2594
2595 def test_sess_cache_no_auto_clear(self):
2596 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002597 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
2598 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
2599 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002600 """
2601 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
2602
2603
2604 def test_sess_cache_no_internal_lookup(self):
2605 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002606 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
2607 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
2608 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002609 """
2610 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
2611
2612
2613 def test_sess_cache_no_internal_store(self):
2614 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002615 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
2616 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
2617 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002618 """
2619 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
2620
2621
2622 def test_sess_cache_no_internal(self):
2623 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002624 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
2625 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
2626 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002627 """
2628 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
2629
2630
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04002631
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002632class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05002633 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002634 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05002635 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002636 def _server(self, sock):
2637 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002638 Create a new server-side SSL :py:obj:`Connection` object wrapped around
2639 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002640 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002641 # Create the server side Connection. This is mostly setup boilerplate
2642 # - use TLSv1, use a particular certificate, etc.
2643 server_ctx = Context(TLSv1_METHOD)
2644 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2645 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2646 server_store = server_ctx.get_cert_store()
2647 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2648 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2649 server_ctx.check_privatekey()
2650 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002651 # Here the Connection is actually created. If None is passed as the 2nd
2652 # parameter, it indicates a memory BIO should be created.
2653 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002654 server_conn.set_accept_state()
2655 return server_conn
2656
2657
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002658 def _client(self, sock):
2659 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002660 Create a new client-side SSL :py:obj:`Connection` object wrapped around
2661 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002662 """
2663 # Now create the client side Connection. Similar boilerplate to the
2664 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002665 client_ctx = Context(TLSv1_METHOD)
2666 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2667 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2668 client_store = client_ctx.get_cert_store()
2669 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
2670 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
2671 client_ctx.check_privatekey()
2672 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002673 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002674 client_conn.set_connect_state()
2675 return client_conn
2676
2677
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002678 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002679 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002680 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002681 reading from the output of each and writing those bytes to the input of
2682 the other and in this way establish a connection and exchange
2683 application-level bytes with each other.
2684 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002685 server_conn = self._server(None)
2686 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002687
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002688 # There should be no key or nonces yet.
2689 self.assertIdentical(server_conn.master_key(), None)
2690 self.assertIdentical(server_conn.client_random(), None)
2691 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002692
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002693 # First, the handshake needs to happen. We'll deliver bytes back and
2694 # forth between the client and server until neither of them feels like
2695 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002696 self.assertIdentical(
2697 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002698
2699 # Now that the handshake is done, there should be a key and nonces.
2700 self.assertNotIdentical(server_conn.master_key(), None)
2701 self.assertNotIdentical(server_conn.client_random(), None)
2702 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04002703 self.assertEquals(server_conn.client_random(), client_conn.client_random())
2704 self.assertEquals(server_conn.server_random(), client_conn.server_random())
2705 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
2706 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002707
2708 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002709 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05002710
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002711 server_conn.write(important_message)
2712 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002713 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002714 (client_conn, important_message))
2715
2716 client_conn.write(important_message[::-1])
2717 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002718 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002719 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05002720
2721
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002722 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05002723 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002724 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002725
2726 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09002727 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002728 this test fails, there must be a problem outside the memory BIO
2729 code, as no memory BIO is involved here). Even though this isn't a
2730 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05002731 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04002732 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05002733
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002734 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05002735 client_conn.send(important_message)
2736 msg = server_conn.recv(1024)
2737 self.assertEqual(msg, important_message)
2738
2739 # Again in the other direction, just for fun.
2740 important_message = important_message[::-1]
2741 server_conn.send(important_message)
2742 msg = client_conn.recv(1024)
2743 self.assertEqual(msg, important_message)
2744
2745
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04002746 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05002747 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002748 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
2749 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05002750 """
2751 context = Context(SSLv3_METHOD)
2752 client = socket()
2753 clientSSL = Connection(context, client)
2754 self.assertRaises( TypeError, clientSSL.bio_read, 100)
2755 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04002756 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002757
2758
2759 def test_outgoingOverflow(self):
2760 """
2761 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002762 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002763 returned and that many bytes from the beginning of the input can be
2764 read from the other end of the connection.
2765 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002766 server = self._server(None)
2767 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002768
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002769 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002770
2771 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002772 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002773 # Sanity check. We're trying to test what happens when the entire
2774 # input can't be sent. If the entire input was sent, this test is
2775 # meaningless.
2776 self.assertTrue(sent < size)
2777
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002778 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002779 self.assertIdentical(receiver, server)
2780
2781 # We can rely on all of these bytes being received at once because
2782 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
2783 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002784
2785
2786 def test_shutdown(self):
2787 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002788 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
2789 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002790 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002791 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002792 server.bio_shutdown()
2793 e = self.assertRaises(Error, server.recv, 1024)
2794 # We don't want WantReadError or ZeroReturnError or anything - it's a
2795 # handshake failure.
2796 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002797
2798
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002799 def test_unexpectedEndOfFile(self):
2800 """
2801 If the connection is lost before an orderly SSL shutdown occurs,
2802 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
2803 "Unexpected EOF".
2804 """
2805 server_conn, client_conn = self._loopback()
2806 client_conn.sock_shutdown(SHUT_RDWR)
2807 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
2808 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
2809
2810
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002811 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002812 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002813 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 -04002814
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002815 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002816 before the client and server are connected to each other. This
2817 function should specify a list of CAs for the server to send to the
2818 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09002819 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002820 times.
2821 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002822 server = self._server(None)
2823 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002824 self.assertEqual(client.get_client_ca_list(), [])
2825 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002826 ctx = server.get_context()
2827 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002828 self.assertEqual(client.get_client_ca_list(), [])
2829 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002830 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002831 self.assertEqual(client.get_client_ca_list(), expected)
2832 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002833
2834
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002835 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002836 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002837 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002838 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002839 """
2840 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002841 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
2842 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
2843 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002844
2845
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002846 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002847 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002848 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002849 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09002850 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002851 after the connection is set up.
2852 """
2853 def no_ca(ctx):
2854 ctx.set_client_ca_list([])
2855 return []
2856 self._check_client_ca_list(no_ca)
2857
2858
2859 def test_set_one_ca_list(self):
2860 """
2861 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002862 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002863 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002864 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002865 X509Name after the connection is set up.
2866 """
2867 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2868 cadesc = cacert.get_subject()
2869 def single_ca(ctx):
2870 ctx.set_client_ca_list([cadesc])
2871 return [cadesc]
2872 self._check_client_ca_list(single_ca)
2873
2874
2875 def test_set_multiple_ca_list(self):
2876 """
2877 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002878 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002879 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002880 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002881 X509Names after the connection is set up.
2882 """
2883 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2884 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2885
2886 sedesc = secert.get_subject()
2887 cldesc = clcert.get_subject()
2888
2889 def multiple_ca(ctx):
2890 L = [sedesc, cldesc]
2891 ctx.set_client_ca_list(L)
2892 return L
2893 self._check_client_ca_list(multiple_ca)
2894
2895
2896 def test_reset_ca_list(self):
2897 """
2898 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09002899 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002900 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002901 """
2902 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2903 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2904 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2905
2906 cadesc = cacert.get_subject()
2907 sedesc = secert.get_subject()
2908 cldesc = clcert.get_subject()
2909
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002910 def changed_ca(ctx):
2911 ctx.set_client_ca_list([sedesc, cldesc])
2912 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002913 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002914 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002915
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002916
2917 def test_mutated_ca_list(self):
2918 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002919 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002920 afterwards, this does not affect the list of CA names sent to the
2921 client.
2922 """
2923 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2924 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2925
2926 cadesc = cacert.get_subject()
2927 sedesc = secert.get_subject()
2928
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002929 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002930 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002931 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002932 L.append(sedesc)
2933 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002934 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002935
2936
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002937 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002938 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002939 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002940 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002941 """
2942 ctx = Context(TLSv1_METHOD)
2943 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002944 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002945 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002946 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002947
2948
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002949 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002950 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002951 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09002952 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002953 """
2954 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2955 cadesc = cacert.get_subject()
2956 def single_ca(ctx):
2957 ctx.add_client_ca(cacert)
2958 return [cadesc]
2959 self._check_client_ca_list(single_ca)
2960
2961
2962 def test_multiple_add_client_ca(self):
2963 """
2964 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09002965 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002966 """
2967 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2968 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2969
2970 cadesc = cacert.get_subject()
2971 sedesc = secert.get_subject()
2972
2973 def multiple_ca(ctx):
2974 ctx.add_client_ca(cacert)
2975 ctx.add_client_ca(secert)
2976 return [cadesc, sedesc]
2977 self._check_client_ca_list(multiple_ca)
2978
2979
2980 def test_set_and_add_client_ca(self):
2981 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002982 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
2983 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002984 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002985 """
2986 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2987 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2988 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2989
2990 cadesc = cacert.get_subject()
2991 sedesc = secert.get_subject()
2992 cldesc = clcert.get_subject()
2993
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002994 def mixed_set_add_ca(ctx):
2995 ctx.set_client_ca_list([cadesc, sedesc])
2996 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002997 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002998 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002999
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003000
3001 def test_set_after_add_client_ca(self):
3002 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003003 A call to :py:obj:`Context.set_client_ca_list` after a call to
3004 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003005 call with the names specified by the latter cal.
3006 """
3007 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3008 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3009 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3010
3011 cadesc = cacert.get_subject()
3012 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003013
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003014 def set_replaces_add_ca(ctx):
3015 ctx.add_client_ca(clcert)
3016 ctx.set_client_ca_list([cadesc])
3017 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003018 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003019 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003020
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003021
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003022
3023class ConnectionBIOTests(TestCase):
3024 """
3025 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3026 """
3027 def test_wantReadError(self):
3028 """
3029 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
3030 if there are no bytes available to be read from the BIO.
3031 """
3032 ctx = Context(TLSv1_METHOD)
3033 conn = Connection(ctx, None)
3034 self.assertRaises(WantReadError, conn.bio_read, 1024)
3035
3036
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003037 def test_buffer_size(self):
3038 """
3039 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3040 number of bytes to read and return.
3041 """
3042 ctx = Context(TLSv1_METHOD)
3043 conn = Connection(ctx, None)
3044 conn.set_connect_state()
3045 try:
3046 conn.do_handshake()
3047 except WantReadError:
3048 pass
3049 data = conn.bio_read(2)
3050 self.assertEqual(2, len(data))
3051
3052
3053 if not PY3:
3054 def test_buffer_size_long(self):
3055 """
3056 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3057 :py:obj:`long` as well as :py:obj:`int`.
3058 """
3059 ctx = Context(TLSv1_METHOD)
3060 conn = Connection(ctx, None)
3061 conn.set_connect_state()
3062 try:
3063 conn.do_handshake()
3064 except WantReadError:
3065 pass
3066 data = conn.bio_read(long(2))
3067 self.assertEqual(2, len(data))
3068
3069
3070
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003071
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003072class InfoConstantTests(TestCase):
3073 """
3074 Tests for assorted constants exposed for use in info callbacks.
3075 """
3076 def test_integers(self):
3077 """
3078 All of the info constants are integers.
3079
3080 This is a very weak test. It would be nice to have one that actually
3081 verifies that as certain info events happen, the value passed to the
3082 info callback matches up with the constant exposed by OpenSSL.SSL.
3083 """
3084 for const in [
3085 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3086 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3087 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3088 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3089 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
3090 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
3091
3092 self.assertTrue(isinstance(const, int))
3093
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003094
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003095if __name__ == '__main__':
3096 main()