blob: a67a37f65b06e0f648d59a9bfd915b8627dd468c [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 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -0400947 self._load_verify_cafile(
948 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
949 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400950
951
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400952 def test_load_verify_invalid_file(self):
953 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900954 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when passed a
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400955 non-existent cafile.
956 """
957 clientContext = Context(TLSv1_METHOD)
958 self.assertRaises(
959 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400960
961
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400962 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400963 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400964 Verify that if path to a directory containing certificate files is
965 passed to ``Context.load_verify_locations`` for the ``capath``
966 parameter, those certificates are used as trust roots for the purposes
967 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400968 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400969 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400970 # Hash values computed manually with c_rehash to avoid depending on
971 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
972 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500973 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400974 cafile = join(capath, name)
975 fObj = open(cafile, 'w')
976 fObj.write(cleartextCertificatePEM.decode('ascii'))
977 fObj.close()
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400978
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400979 self._load_verify_locations_test(None, capath)
980
981
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400982 def test_load_verify_directory_bytes_capath(self):
983 """
984 :py:obj:`Context.load_verify_locations` accepts a directory name as a
985 ``bytes`` instance and uses the certificates within for verification
986 purposes.
987 """
988 self._load_verify_directory_locations_capath(
989 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
990 )
991
992
993 def test_load_verify_directory_unicode_capath(self):
994 """
995 :py:obj:`Context.load_verify_locations` accepts a directory name as a
996 ``unicode`` instance and uses the certificates within for verification
997 purposes.
998 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -0400999 self._load_verify_directory_locations_capath(
1000 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
1001 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001002
1003
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001004 def test_load_verify_locations_wrong_args(self):
1005 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001006 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if called with
1007 the wrong number of arguments or with non-:py:obj:`str` arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001008 """
1009 context = Context(TLSv1_METHOD)
1010 self.assertRaises(TypeError, context.load_verify_locations)
1011 self.assertRaises(TypeError, context.load_verify_locations, object())
1012 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
1013 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
1014
1015
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001016 if platform == "win32":
1017 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001018 "See LP#404343 and LP#404344."
1019 else:
1020 def test_set_default_verify_paths(self):
1021 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001022 :py:obj:`Context.set_default_verify_paths` causes the platform-specific CA
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001023 certificate locations to be used for verification purposes.
1024 """
1025 # Testing this requires a server with a certificate signed by one of
1026 # the CAs in the platform CA location. Getting one of those costs
1027 # money. Fortunately (or unfortunately, depending on your
1028 # perspective), it's easy to think of a public server on the
1029 # internet which has such a certificate. Connecting to the network
1030 # in a unit test is bad, but it's the only way I can think of to
1031 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001032
Alex Gaynorb586da32014-11-15 09:22:21 -08001033 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
1034 context = Context(TLSv1_METHOD)
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001035 context.set_default_verify_paths()
1036 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02001037 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001038 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001039
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001040 client = socket()
1041 client.connect(('verisign.com', 443))
1042 clientSSL = Connection(context, client)
1043 clientSSL.set_connect_state()
1044 clientSSL.do_handshake()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001045 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001046 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001047
1048
1049 def test_set_default_verify_paths_signature(self):
1050 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001051 :py:obj:`Context.set_default_verify_paths` takes no arguments and raises
1052 :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001053 """
1054 context = Context(TLSv1_METHOD)
1055 self.assertRaises(TypeError, context.set_default_verify_paths, None)
1056 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
1057 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001058
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001059
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001060 def test_add_extra_chain_cert_invalid_cert(self):
1061 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001062 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if called with
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001063 other than one argument or if called with an object which is not an
Jonathan Ballet648875f2011-07-16 14:14:58 +09001064 instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001065 """
1066 context = Context(TLSv1_METHOD)
1067 self.assertRaises(TypeError, context.add_extra_chain_cert)
1068 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
1069 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
1070
1071
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001072 def _handshake_test(self, serverContext, clientContext):
1073 """
1074 Verify that a client and server created with the given contexts can
1075 successfully handshake and communicate.
1076 """
1077 serverSocket, clientSocket = socket_pair()
1078
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001079 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001080 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001081
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001082 client = Connection(clientContext, clientSocket)
1083 client.set_connect_state()
1084
1085 # Make them talk to each other.
1086 # self._interactInMemory(client, server)
1087 for i in range(3):
1088 for s in [client, server]:
1089 try:
1090 s.do_handshake()
1091 except WantReadError:
1092 pass
1093
1094
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001095 def test_set_verify_callback_connection_argument(self):
1096 """
1097 The first argument passed to the verify callback is the
1098 :py:class:`Connection` instance for which verification is taking place.
1099 """
1100 serverContext = Context(TLSv1_METHOD)
1101 serverContext.use_privatekey(
1102 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1103 serverContext.use_certificate(
1104 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1105 serverConnection = Connection(serverContext, None)
1106
1107 class VerifyCallback(object):
1108 def callback(self, connection, *args):
1109 self.connection = connection
1110 return 1
1111
1112 verify = VerifyCallback()
1113 clientContext = Context(TLSv1_METHOD)
1114 clientContext.set_verify(VERIFY_PEER, verify.callback)
1115 clientConnection = Connection(clientContext, None)
1116 clientConnection.set_connect_state()
1117
1118 self._handshakeInMemory(clientConnection, serverConnection)
1119
1120 self.assertIdentical(verify.connection, clientConnection)
1121
1122
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001123 def test_set_verify_callback_exception(self):
1124 """
1125 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1126 exception, verification fails and the exception is propagated to the
1127 caller of :py:obj:`Connection.do_handshake`.
1128 """
1129 serverContext = Context(TLSv1_METHOD)
1130 serverContext.use_privatekey(
1131 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1132 serverContext.use_certificate(
1133 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1134
1135 clientContext = Context(TLSv1_METHOD)
1136 def verify_callback(*args):
1137 raise Exception("silly verify failure")
1138 clientContext.set_verify(VERIFY_PEER, verify_callback)
1139
1140 exc = self.assertRaises(
1141 Exception, self._handshake_test, serverContext, clientContext)
1142 self.assertEqual("silly verify failure", str(exc))
1143
1144
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001145 def test_add_extra_chain_cert(self):
1146 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001147 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509` instance to add to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001148 the certificate chain.
1149
Jonathan Ballet648875f2011-07-16 14:14:58 +09001150 See :py:obj:`_create_certificate_chain` for the details of the certificate
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001151 chain tested.
1152
1153 The chain is tested by starting a server with scert and connecting
1154 to it with a client which trusts cacert and requires verification to
1155 succeed.
1156 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001157 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001158 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1159
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001160 # Dump the CA certificate to a file because that's the only way to load
1161 # it as a trusted CA in the client context.
1162 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001163 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001164 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001165 fObj.close()
1166
1167 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001168 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001169 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001170 fObj.close()
1171
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001172 # Create the server context
1173 serverContext = Context(TLSv1_METHOD)
1174 serverContext.use_privatekey(skey)
1175 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001176 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001177 serverContext.add_extra_chain_cert(icert)
1178
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001179 # Create the client
1180 clientContext = Context(TLSv1_METHOD)
1181 clientContext.set_verify(
1182 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001183 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001184
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001185 # Try it out.
1186 self._handshake_test(serverContext, clientContext)
1187
1188
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001189 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001190 """
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001191 Verify that :py:obj:`Context.use_certificate_chain_file` reads a
1192 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001193
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001194 The chain is tested by starting a server with scert and connecting to
1195 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001196 succeed.
1197 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001198 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001199 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1200
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001201 makedirs(certdir)
1202
1203 if isinstance(certdir, binary_type):
1204 chainFile = join(certdir, b("chain.pem"))
1205 caFile = join(certdir, b("ca.pem"))
1206 else:
Jean-Paul Calderonee21139c2015-04-12 10:15:50 -04001207 chainFile = join(certdir, u("chain.pem"))
1208 caFile = join(certdir, u("ca.pem"))
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001209
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001210 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001211 with open(chainFile, 'wb') as fObj:
1212 # Most specific to least general.
1213 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1214 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1215 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1216
1217 with open(caFile, 'w') as fObj:
1218 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001219
1220 serverContext = Context(TLSv1_METHOD)
1221 serverContext.use_certificate_chain_file(chainFile)
1222 serverContext.use_privatekey(skey)
1223
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001224 clientContext = Context(TLSv1_METHOD)
1225 clientContext.set_verify(
1226 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001227 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001228
1229 self._handshake_test(serverContext, clientContext)
1230
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001231
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001232 def test_use_certificate_chain_file_bytes(self):
1233 """
1234 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1235 an instance of ``bytes``) to specify additional certificates to use to
1236 construct and verify a trust chain.
1237 """
1238 self._use_certificate_chain_file_test(
1239 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
1240 )
1241
1242
1243 def test_use_certificate_chain_file_unicode(self):
1244 """
1245 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1246 an instance of ``unicode``) to specify additional certificates to use
1247 to construct and verify a trust chain.
1248 """
1249 self._use_certificate_chain_file_test(
1250 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
1251 )
1252
1253
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001254 def test_use_certificate_chain_file_wrong_args(self):
1255 """
1256 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1257 if passed zero or more than one argument or when passed a non-byte
1258 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error` when
1259 passed a bad chain file name (for example, the name of a file which does
1260 not exist).
1261 """
1262 context = Context(TLSv1_METHOD)
1263 self.assertRaises(TypeError, context.use_certificate_chain_file)
1264 self.assertRaises(TypeError, context.use_certificate_chain_file, object())
1265 self.assertRaises(TypeError, context.use_certificate_chain_file, b"foo", object())
1266
1267 self.assertRaises(Error, context.use_certificate_chain_file, self.mktemp())
1268
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001269 # XXX load_client_ca
1270 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001271
1272 def test_get_verify_mode_wrong_args(self):
1273 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001274 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001275 arguments.
1276 """
1277 context = Context(TLSv1_METHOD)
1278 self.assertRaises(TypeError, context.get_verify_mode, None)
1279
1280
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001281 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001282 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001283 :py:obj:`Context.get_verify_mode` returns the verify mode flags previously
1284 passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001285 """
1286 context = Context(TLSv1_METHOD)
1287 self.assertEquals(context.get_verify_mode(), 0)
1288 context.set_verify(
1289 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1290 self.assertEquals(
1291 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1292
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001293
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001294 if not PY3:
1295 def test_set_verify_mode_long(self):
1296 """
1297 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1298 type :py:obj:`long` as well as :py:obj:`int`.
1299 """
1300 context = Context(TLSv1_METHOD)
1301 self.assertEquals(context.get_verify_mode(), 0)
1302 context.set_verify(
1303 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None)
1304 self.assertEquals(
1305 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1306
1307
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001308 def test_load_tmp_dh_wrong_args(self):
1309 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001310 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
1311 number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001312 """
1313 context = Context(TLSv1_METHOD)
1314 self.assertRaises(TypeError, context.load_tmp_dh)
1315 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1316 self.assertRaises(TypeError, context.load_tmp_dh, object())
1317
1318
1319 def test_load_tmp_dh_missing_file(self):
1320 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001321 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the specified file
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001322 does not exist.
1323 """
1324 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001325 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001326
1327
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001328 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001329 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001330 with open(dhfilename, "w") as dhfile:
1331 dhfile.write(dhparam)
1332
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001333 context.load_tmp_dh(dhfilename)
1334 # XXX What should I assert here? -exarkun
1335
1336
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001337 def test_load_tmp_dh_bytes(self):
1338 """
1339 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1340 specified file (given as ``bytes``).
1341 """
1342 self._load_tmp_dh_test(
1343 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
1344 )
1345
1346
1347 def test_load_tmp_dh_unicode(self):
1348 """
1349 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1350 specified file (given as ``unicode``).
1351 """
1352 self._load_tmp_dh_test(
1353 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
1354 )
1355
1356
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001357 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001358 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001359 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001360 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001361 """
1362 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001363 for curve in get_elliptic_curves():
1364 # The only easily "assertable" thing is that it does not raise an
1365 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001366 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001367
1368
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001369 def test_set_cipher_list_bytes(self):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001370 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001371 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
1372 ciphers which connections created with the context object will be able
1373 to choose from.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001374 """
1375 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001376 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001377 conn = Connection(context, None)
1378 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001379
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001380
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001381 def test_set_cipher_list_text(self):
1382 """
1383 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
1384 the ciphers which connections created with the context object will be
1385 able to choose from.
1386 """
1387 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -05001388 context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001389 conn = Connection(context, None)
1390 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
1391
1392
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001393 def test_set_cipher_list_wrong_args(self):
1394 """
Jean-Paul Calderone17044832014-01-18 10:20:11 -05001395 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
1396 passed zero arguments or more than one argument or when passed a
1397 non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001398 passed an incorrect cipher list string.
1399 """
1400 context = Context(TLSv1_METHOD)
1401 self.assertRaises(TypeError, context.set_cipher_list)
1402 self.assertRaises(TypeError, context.set_cipher_list, object())
1403 self.assertRaises(TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object())
1404
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001405 self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001406
1407
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001408 def test_set_session_cache_mode_wrong_args(self):
1409 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001410 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1411 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001412 """
1413 context = Context(TLSv1_METHOD)
1414 self.assertRaises(TypeError, context.set_session_cache_mode)
1415 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1416
1417
1418 def test_get_session_cache_mode_wrong_args(self):
1419 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001420 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1421 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001422 """
1423 context = Context(TLSv1_METHOD)
1424 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1425
1426
1427 def test_session_cache_mode(self):
1428 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001429 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1430 cached. The setting can be retrieved via
1431 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001432 """
1433 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001434 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001435 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1436 self.assertEqual(SESS_CACHE_OFF, off)
1437 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1438
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001439 if not PY3:
1440 def test_session_cache_mode_long(self):
1441 """
1442 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1443 of type :py:obj:`long` as well as :py:obj:`int`.
1444 """
1445 context = Context(TLSv1_METHOD)
1446 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1447 self.assertEqual(
1448 SESS_CACHE_BOTH, context.get_session_cache_mode())
1449
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001450
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001451 def test_get_cert_store(self):
1452 """
1453 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store` instance.
1454 """
1455 context = Context(TLSv1_METHOD)
1456 store = context.get_cert_store()
1457 self.assertIsInstance(store, X509Store)
1458
1459
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001460
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001461class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1462 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001463 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
1464 :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001465 """
1466 def test_wrong_args(self):
1467 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001468 :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001469 with other than one argument.
1470 """
1471 context = Context(TLSv1_METHOD)
1472 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1473 self.assertRaises(
1474 TypeError, context.set_tlsext_servername_callback, 1, 2)
1475
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001476
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001477 def test_old_callback_forgotten(self):
1478 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001479 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001480 callback, the one it replaces is dereferenced.
1481 """
1482 def callback(connection):
1483 pass
1484
1485 def replacement(connection):
1486 pass
1487
1488 context = Context(TLSv1_METHOD)
1489 context.set_tlsext_servername_callback(callback)
1490
1491 tracker = ref(callback)
1492 del callback
1493
1494 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001495
1496 # One run of the garbage collector happens to work on CPython. PyPy
1497 # doesn't collect the underlying object until a second run for whatever
1498 # reason. That's fine, it still demonstrates our code has properly
1499 # dropped the reference.
1500 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001501 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001502
1503 callback = tracker()
1504 if callback is not None:
1505 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001506 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001507 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001508
1509
1510 def test_no_servername(self):
1511 """
1512 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001513 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
1514 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001515 """
1516 args = []
1517 def servername(conn):
1518 args.append((conn, conn.get_servername()))
1519 context = Context(TLSv1_METHOD)
1520 context.set_tlsext_servername_callback(servername)
1521
1522 # Lose our reference to it. The Context is responsible for keeping it
1523 # alive now.
1524 del servername
1525 collect()
1526
1527 # Necessary to actually accept the connection
1528 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1529 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1530
1531 # Do a little connection to trigger the logic
1532 server = Connection(context, None)
1533 server.set_accept_state()
1534
1535 client = Connection(Context(TLSv1_METHOD), None)
1536 client.set_connect_state()
1537
1538 self._interactInMemory(server, client)
1539
1540 self.assertEqual([(server, None)], args)
1541
1542
1543 def test_servername(self):
1544 """
1545 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +09001546 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
1547 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001548 """
1549 args = []
1550 def servername(conn):
1551 args.append((conn, conn.get_servername()))
1552 context = Context(TLSv1_METHOD)
1553 context.set_tlsext_servername_callback(servername)
1554
1555 # Necessary to actually accept the connection
1556 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1557 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1558
1559 # Do a little connection to trigger the logic
1560 server = Connection(context, None)
1561 server.set_accept_state()
1562
1563 client = Connection(Context(TLSv1_METHOD), None)
1564 client.set_connect_state()
1565 client.set_tlsext_host_name(b("foo1.example.com"))
1566
1567 self._interactInMemory(server, client)
1568
1569 self.assertEqual([(server, b("foo1.example.com"))], args)
1570
1571
1572
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001573class SessionTests(TestCase):
1574 """
1575 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1576 """
1577 def test_construction(self):
1578 """
1579 :py:class:`Session` can be constructed with no arguments, creating a new
1580 instance of that type.
1581 """
1582 new_session = Session()
1583 self.assertTrue(isinstance(new_session, Session))
1584
1585
1586 def test_construction_wrong_args(self):
1587 """
1588 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
1589 is raised.
1590 """
1591 self.assertRaises(TypeError, Session, 123)
1592 self.assertRaises(TypeError, Session, "hello")
1593 self.assertRaises(TypeError, Session, object())
1594
1595
1596
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001597class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05001598 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001599 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001600 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001601 # XXX get_peer_certificate -> None
1602 # XXX sock_shutdown
1603 # XXX master_key -> TypeError
1604 # XXX server_random -> TypeError
1605 # XXX state_string
1606 # XXX connect -> TypeError
1607 # XXX connect_ex -> TypeError
1608 # XXX set_connect_state -> TypeError
1609 # XXX set_accept_state -> TypeError
1610 # XXX renegotiate_pending
1611 # XXX do_handshake -> TypeError
1612 # XXX bio_read -> TypeError
1613 # XXX recv -> TypeError
1614 # XXX send -> TypeError
1615 # XXX bio_write -> TypeError
1616
Rick Deane15b1472009-07-09 15:53:42 -05001617 def test_type(self):
1618 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001619 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001620 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05001621 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001622 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05001623 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001624 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05001625
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001626
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001627 def test_get_context(self):
1628 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001629 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
1630 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001631 """
1632 context = Context(TLSv1_METHOD)
1633 connection = Connection(context, None)
1634 self.assertIdentical(connection.get_context(), context)
1635
1636
1637 def test_get_context_wrong_args(self):
1638 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001639 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001640 arguments.
1641 """
1642 connection = Connection(Context(TLSv1_METHOD), None)
1643 self.assertRaises(TypeError, connection.get_context, None)
1644
1645
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001646 def test_set_context_wrong_args(self):
1647 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001648 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
1649 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001650 than 1.
1651 """
1652 ctx = Context(TLSv1_METHOD)
1653 connection = Connection(ctx, None)
1654 self.assertRaises(TypeError, connection.set_context)
1655 self.assertRaises(TypeError, connection.set_context, object())
1656 self.assertRaises(TypeError, connection.set_context, "hello")
1657 self.assertRaises(TypeError, connection.set_context, 1)
1658 self.assertRaises(TypeError, connection.set_context, 1, 2)
1659 self.assertRaises(
1660 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
1661 self.assertIdentical(ctx, connection.get_context())
1662
1663
1664 def test_set_context(self):
1665 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001666 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001667 for the connection.
1668 """
1669 original = Context(SSLv23_METHOD)
1670 replacement = Context(TLSv1_METHOD)
1671 connection = Connection(original, None)
1672 connection.set_context(replacement)
1673 self.assertIdentical(replacement, connection.get_context())
1674 # Lose our references to the contexts, just in case the Connection isn't
1675 # properly managing its own contributions to their reference counts.
1676 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001677 collect()
1678
1679
1680 def test_set_tlsext_host_name_wrong_args(self):
1681 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001682 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001683 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09001684 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001685 """
1686 conn = Connection(Context(TLSv1_METHOD), None)
1687 self.assertRaises(TypeError, conn.set_tlsext_host_name)
1688 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
1689 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
1690 self.assertRaises(
1691 TypeError, conn.set_tlsext_host_name, b("with\0null"))
1692
1693 if version_info >= (3,):
1694 # On Python 3.x, don't accidentally implicitly convert from text.
1695 self.assertRaises(
1696 TypeError,
1697 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001698
1699
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001700 def test_get_servername_wrong_args(self):
1701 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001702 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001703 arguments.
1704 """
1705 connection = Connection(Context(TLSv1_METHOD), None)
1706 self.assertRaises(TypeError, connection.get_servername, object())
1707 self.assertRaises(TypeError, connection.get_servername, 1)
1708 self.assertRaises(TypeError, connection.get_servername, "hello")
1709
1710
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001711 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001712 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001713 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001714 immediate read.
1715 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001716 connection = Connection(Context(TLSv1_METHOD), None)
1717 self.assertEquals(connection.pending(), 0)
1718
1719
1720 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001721 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001722 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001723 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001724 connection = Connection(Context(TLSv1_METHOD), None)
1725 self.assertRaises(TypeError, connection.pending, None)
1726
1727
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001728 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001729 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001730 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001731 argument or with the wrong number of arguments.
1732 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001733 connection = Connection(Context(TLSv1_METHOD), socket())
1734 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001735 self.assertRaises(TypeError, connection.connect)
1736 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001737
1738
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001739 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001740 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001741 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001742 connect method raises it.
1743 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001744 client = socket()
1745 context = Context(TLSv1_METHOD)
1746 clientSSL = Connection(context, client)
1747 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04001748 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001749
1750
1751 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001752 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001753 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001754 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001755 port = socket()
1756 port.bind(('', 0))
1757 port.listen(3)
1758
1759 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001760 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
1761 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001762
1763
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001764 if platform == "darwin":
1765 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
1766 else:
1767 def test_connect_ex(self):
1768 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001769 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001770 errno instead of raising an exception.
1771 """
1772 port = socket()
1773 port.bind(('', 0))
1774 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001775
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001776 clientSSL = Connection(Context(TLSv1_METHOD), socket())
1777 clientSSL.setblocking(False)
1778 result = clientSSL.connect_ex(port.getsockname())
1779 expected = (EINPROGRESS, EWOULDBLOCK)
1780 self.assertTrue(
1781 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001782
1783
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001784 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001785 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001786 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001787 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001788 connection = Connection(Context(TLSv1_METHOD), socket())
1789 self.assertRaises(TypeError, connection.accept, None)
1790
1791
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001792 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001793 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001794 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
1795 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001796 connection originated from.
1797 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001798 ctx = Context(TLSv1_METHOD)
1799 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1800 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001801 port = socket()
1802 portSSL = Connection(ctx, port)
1803 portSSL.bind(('', 0))
1804 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001805
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001806 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001807
1808 # Calling portSSL.getsockname() here to get the server IP address sounds
1809 # great, but frequently fails on Windows.
1810 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001811
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001812 serverSSL, address = portSSL.accept()
1813
1814 self.assertTrue(isinstance(serverSSL, Connection))
1815 self.assertIdentical(serverSSL.get_context(), ctx)
1816 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001817
1818
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001819 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001820 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001821 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001822 number of arguments or with arguments other than integers.
1823 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001824 connection = Connection(Context(TLSv1_METHOD), None)
1825 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04001826 self.assertRaises(TypeError, connection.get_shutdown, None)
1827 self.assertRaises(TypeError, connection.set_shutdown)
1828 self.assertRaises(TypeError, connection.set_shutdown, None)
1829 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001830
1831
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001832 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001833 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001834 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001835 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001836 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001837 self.assertFalse(server.shutdown())
1838 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001839 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001840 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
1841 client.shutdown()
1842 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
1843 self.assertRaises(ZeroReturnError, server.recv, 1024)
1844 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001845
1846
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001847 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001848 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001849 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001850 process.
1851 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001852 connection = Connection(Context(TLSv1_METHOD), socket())
1853 connection.set_shutdown(RECEIVED_SHUTDOWN)
1854 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1855
1856
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05001857 if not PY3:
1858 def test_set_shutdown_long(self):
1859 """
1860 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
1861 of type :py:obj:`long` as well as :py:obj:`int`.
1862 """
1863 connection = Connection(Context(TLSv1_METHOD), socket())
1864 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
1865 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1866
1867
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001868 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001869 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001870 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
1871 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001872 with any arguments.
1873 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001874 conn = Connection(Context(TLSv1_METHOD), None)
1875 self.assertRaises(TypeError, conn.get_app_data, None)
1876 self.assertRaises(TypeError, conn.set_app_data)
1877 self.assertRaises(TypeError, conn.set_app_data, None, None)
1878
1879
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001880 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001881 """
1882 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001883 :py:obj:`Connection.set_app_data` and later retrieved with
1884 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001885 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001886 conn = Connection(Context(TLSv1_METHOD), None)
1887 app_data = object()
1888 conn.set_app_data(app_data)
1889 self.assertIdentical(conn.get_app_data(), app_data)
1890
1891
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001892 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001893 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001894 :py:obj:`Connection.makefile` is not implemented and calling that method raises
1895 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001896 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001897 conn = Connection(Context(TLSv1_METHOD), None)
1898 self.assertRaises(NotImplementedError, conn.makefile)
1899
1900
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001901 def test_get_peer_cert_chain_wrong_args(self):
1902 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001903 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001904 arguments.
1905 """
1906 conn = Connection(Context(TLSv1_METHOD), None)
1907 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
1908 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
1909 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
1910 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
1911
1912
1913 def test_get_peer_cert_chain(self):
1914 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001915 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001916 the connected server returned for the certification verification.
1917 """
1918 chain = _create_certificate_chain()
1919 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1920
1921 serverContext = Context(TLSv1_METHOD)
1922 serverContext.use_privatekey(skey)
1923 serverContext.use_certificate(scert)
1924 serverContext.add_extra_chain_cert(icert)
1925 serverContext.add_extra_chain_cert(cacert)
1926 server = Connection(serverContext, None)
1927 server.set_accept_state()
1928
1929 # Create the client
1930 clientContext = Context(TLSv1_METHOD)
1931 clientContext.set_verify(VERIFY_NONE, verify_cb)
1932 client = Connection(clientContext, None)
1933 client.set_connect_state()
1934
1935 self._interactInMemory(client, server)
1936
1937 chain = client.get_peer_cert_chain()
1938 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001939 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001940 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001941 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001942 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001943 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001944 "Authority Certificate", chain[2].get_subject().CN)
1945
1946
1947 def test_get_peer_cert_chain_none(self):
1948 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001949 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001950 certificate chain.
1951 """
1952 ctx = Context(TLSv1_METHOD)
1953 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1954 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1955 server = Connection(ctx, None)
1956 server.set_accept_state()
1957 client = Connection(Context(TLSv1_METHOD), None)
1958 client.set_connect_state()
1959 self._interactInMemory(client, server)
1960 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001961
1962
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001963 def test_get_session_wrong_args(self):
1964 """
1965 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
1966 with any arguments.
1967 """
1968 ctx = Context(TLSv1_METHOD)
1969 server = Connection(ctx, None)
1970 self.assertRaises(TypeError, server.get_session, 123)
1971 self.assertRaises(TypeError, server.get_session, "hello")
1972 self.assertRaises(TypeError, server.get_session, object())
1973
1974
1975 def test_get_session_unconnected(self):
1976 """
1977 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
1978 an object which has not been connected.
1979 """
1980 ctx = Context(TLSv1_METHOD)
1981 server = Connection(ctx, None)
1982 session = server.get_session()
1983 self.assertIdentical(None, session)
1984
1985
1986 def test_server_get_session(self):
1987 """
1988 On the server side of a connection, :py:obj:`Connection.get_session`
1989 returns a :py:class:`Session` instance representing the SSL session for
1990 that connection.
1991 """
1992 server, client = self._loopback()
1993 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001994 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001995
1996
1997 def test_client_get_session(self):
1998 """
1999 On the client side of a connection, :py:obj:`Connection.get_session`
2000 returns a :py:class:`Session` instance representing the SSL session for
2001 that connection.
2002 """
2003 server, client = self._loopback()
2004 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002005 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002006
2007
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002008 def test_set_session_wrong_args(self):
2009 """
2010 If called with an object that is not an instance of :py:class:`Session`,
2011 or with other than one argument, :py:obj:`Connection.set_session` raises
2012 :py:obj:`TypeError`.
2013 """
2014 ctx = Context(TLSv1_METHOD)
2015 connection = Connection(ctx, None)
2016 self.assertRaises(TypeError, connection.set_session)
2017 self.assertRaises(TypeError, connection.set_session, 123)
2018 self.assertRaises(TypeError, connection.set_session, "hello")
2019 self.assertRaises(TypeError, connection.set_session, object())
2020 self.assertRaises(
2021 TypeError, connection.set_session, Session(), Session())
2022
2023
2024 def test_client_set_session(self):
2025 """
2026 :py:obj:`Connection.set_session`, when used prior to a connection being
2027 established, accepts a :py:class:`Session` instance and causes an
2028 attempt to re-use the session it represents when the SSL handshake is
2029 performed.
2030 """
2031 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2032 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2033 ctx = Context(TLSv1_METHOD)
2034 ctx.use_privatekey(key)
2035 ctx.use_certificate(cert)
2036 ctx.set_session_id("unity-test")
2037
2038 def makeServer(socket):
2039 server = Connection(ctx, socket)
2040 server.set_accept_state()
2041 return server
2042
2043 originalServer, originalClient = self._loopback(
2044 serverFactory=makeServer)
2045 originalSession = originalClient.get_session()
2046
2047 def makeClient(socket):
2048 client = self._loopbackClientFactory(socket)
2049 client.set_session(originalSession)
2050 return client
2051 resumedServer, resumedClient = self._loopback(
2052 serverFactory=makeServer,
2053 clientFactory=makeClient)
2054
2055 # This is a proxy: in general, we have no access to any unique
2056 # identifier for the session (new enough versions of OpenSSL expose a
2057 # hash which could be usable, but "new enough" is very, very new).
2058 # Instead, exploit the fact that the master key is re-used if the
2059 # session is re-used. As long as the master key for the two connections
2060 # is the same, the session was re-used!
2061 self.assertEqual(
2062 originalServer.master_key(), resumedServer.master_key())
2063
2064
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002065 def test_set_session_wrong_method(self):
2066 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002067 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
2068 instance associated with a context using a different SSL method than the
2069 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
2070 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002071 """
2072 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2073 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2074 ctx = Context(TLSv1_METHOD)
2075 ctx.use_privatekey(key)
2076 ctx.use_certificate(cert)
2077 ctx.set_session_id("unity-test")
2078
2079 def makeServer(socket):
2080 server = Connection(ctx, socket)
2081 server.set_accept_state()
2082 return server
2083
2084 originalServer, originalClient = self._loopback(
2085 serverFactory=makeServer)
2086 originalSession = originalClient.get_session()
2087
2088 def makeClient(socket):
2089 # Intentionally use a different, incompatible method here.
2090 client = Connection(Context(SSLv3_METHOD), socket)
2091 client.set_connect_state()
2092 client.set_session(originalSession)
2093 return client
2094
2095 self.assertRaises(
2096 Error,
2097 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2098
2099
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002100 def test_wantWriteError(self):
2101 """
2102 :py:obj:`Connection` methods which generate output raise
2103 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2104 fail indicating a should-write state.
2105 """
2106 client_socket, server_socket = socket_pair()
2107 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002108 # anything. Only write a single byte at a time so we can be sure we
2109 # completely fill the buffer. Even though the socket API is allowed to
2110 # signal a short write via its return value it seems this doesn't
2111 # always happen on all platforms (FreeBSD and OS X particular) for the
2112 # very last bit of available buffer space.
2113 msg = b"x"
2114 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002115 try:
2116 client_socket.send(msg)
2117 except error as e:
2118 if e.errno == EWOULDBLOCK:
2119 break
2120 raise
2121 else:
2122 self.fail(
2123 "Failed to fill socket buffer, cannot test BIO want write")
2124
2125 ctx = Context(TLSv1_METHOD)
2126 conn = Connection(ctx, client_socket)
2127 # Client's speak first, so make it an SSL client
2128 conn.set_connect_state()
2129 self.assertRaises(WantWriteError, conn.do_handshake)
2130
2131 # XXX want_read
2132
Fedor Brunner416f4a12014-03-28 13:18:38 +01002133 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002134 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002135 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2136 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002137 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002138 ctx = Context(TLSv1_METHOD)
2139 connection = Connection(ctx, None)
2140 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002141
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002142
Fedor Brunner416f4a12014-03-28 13:18:38 +01002143 def test_get_peer_finished_before_connect(self):
2144 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002145 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2146 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002147 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002148 ctx = Context(TLSv1_METHOD)
2149 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002150 self.assertEqual(connection.get_peer_finished(), None)
2151
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002152
Fedor Brunner416f4a12014-03-28 13:18:38 +01002153 def test_get_finished(self):
2154 """
2155 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002156 message send from client, or server. Finished messages are send during
2157 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002158 """
2159
Fedor Brunner5747b932014-03-05 14:22:34 +01002160 server, client = self._loopback()
2161
2162 self.assertNotEqual(server.get_finished(), None)
2163 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002164
Jean-Paul Calderoned979f232014-03-30 11:58:00 -04002165
Fedor Brunner416f4a12014-03-28 13:18:38 +01002166 def test_get_peer_finished(self):
2167 """
2168 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002169 message received from client, or server. Finished messages are send
2170 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002171 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002172 server, client = self._loopback()
2173
2174 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002175 self.assertTrue(len(server.get_peer_finished()) > 0)
2176
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002177
Fedor Brunner416f4a12014-03-28 13:18:38 +01002178 def test_tls_finished_message_symmetry(self):
2179 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002180 The TLS Finished message send by server must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002181 received by client.
2182
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002183 The TLS Finished message send by client must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002184 received by server.
2185 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002186 server, client = self._loopback()
2187
Fedor Brunner5747b932014-03-05 14:22:34 +01002188 self.assertEqual(server.get_finished(), client.get_peer_finished())
2189 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002190
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002191
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002192 def test_get_cipher_name_before_connect(self):
2193 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002194 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2195 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002196 """
2197 ctx = Context(TLSv1_METHOD)
2198 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002199 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002200
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002201
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002202 def test_get_cipher_name(self):
2203 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002204 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2205 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002206 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002207 server, client = self._loopback()
2208 server_cipher_name, client_cipher_name = \
2209 server.get_cipher_name(), client.get_cipher_name()
2210
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002211 self.assertIsInstance(server_cipher_name, text_type)
2212 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002213
2214 self.assertEqual(server_cipher_name, client_cipher_name)
2215
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002216
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002217 def test_get_cipher_version_before_connect(self):
2218 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002219 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2220 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002221 """
2222 ctx = Context(TLSv1_METHOD)
2223 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002224 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002225
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002226
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002227 def test_get_cipher_version(self):
2228 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002229 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2230 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002231 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002232 server, client = self._loopback()
2233 server_cipher_version, client_cipher_version = \
2234 server.get_cipher_version(), client.get_cipher_version()
2235
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002236 self.assertIsInstance(server_cipher_version, text_type)
2237 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002238
2239 self.assertEqual(server_cipher_version, client_cipher_version)
2240
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002241
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002242 def test_get_cipher_bits_before_connect(self):
2243 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002244 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2245 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002246 """
2247 ctx = Context(TLSv1_METHOD)
2248 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002249 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002250
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002251
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002252 def test_get_cipher_bits(self):
2253 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002254 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2255 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002256 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002257 server, client = self._loopback()
2258 server_cipher_bits, client_cipher_bits = \
2259 server.get_cipher_bits(), client.get_cipher_bits()
2260
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002261 self.assertIsInstance(server_cipher_bits, int)
2262 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002263
2264 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002265
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002266
2267
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002268class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002269 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002270 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002271 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002272 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002273 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002274 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002275 arguments.
2276 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002277 connection = Connection(Context(TLSv1_METHOD), None)
2278 self.assertRaises(TypeError, connection.get_cipher_list, None)
2279
2280
2281 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002282 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002283 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2284 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002285 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002286 connection = Connection(Context(TLSv1_METHOD), None)
2287 ciphers = connection.get_cipher_list()
2288 self.assertTrue(isinstance(ciphers, list))
2289 for cipher in ciphers:
2290 self.assertTrue(isinstance(cipher, str))
2291
2292
2293
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002294class ConnectionSendTests(TestCase, _LoopbackMixin):
2295 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002296 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002297 """
2298 def test_wrong_args(self):
2299 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002300 When called with arguments other than string argument for its first
2301 parameter or more than two arguments, :py:obj:`Connection.send` raises
2302 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002303 """
2304 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002305 self.assertRaises(TypeError, connection.send)
2306 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002307 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002308
2309
2310 def test_short_bytes(self):
2311 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002312 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002313 and returns the number of bytes sent.
2314 """
2315 server, client = self._loopback()
2316 count = server.send(b('xy'))
2317 self.assertEquals(count, 2)
2318 self.assertEquals(client.recv(2), b('xy'))
2319
2320 try:
2321 memoryview
2322 except NameError:
2323 "cannot test sending memoryview without memoryview"
2324 else:
2325 def test_short_memoryview(self):
2326 """
2327 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002328 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002329 bytes sent.
2330 """
2331 server, client = self._loopback()
2332 count = server.send(memoryview(b('xy')))
2333 self.assertEquals(count, 2)
2334 self.assertEquals(client.recv(2), b('xy'))
2335
2336
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002337 try:
2338 buffer
2339 except NameError:
2340 "cannot test sending buffer without buffer"
2341 else:
2342 def test_short_buffer(self):
2343 """
2344 When passed a buffer containing a small number of bytes,
2345 :py:obj:`Connection.send` transmits all of them and returns the number of
2346 bytes sent.
2347 """
2348 server, client = self._loopback()
2349 count = server.send(buffer(b('xy')))
2350 self.assertEquals(count, 2)
2351 self.assertEquals(client.recv(2), b('xy'))
2352
2353
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002354
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002355class ConnectionSendallTests(TestCase, _LoopbackMixin):
2356 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002357 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002358 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002359 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002360 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002361 When called with arguments other than a string argument for its first
2362 parameter or with more than two arguments, :py:obj:`Connection.sendall`
2363 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002364 """
2365 connection = Connection(Context(TLSv1_METHOD), None)
2366 self.assertRaises(TypeError, connection.sendall)
2367 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002368 self.assertRaises(
2369 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002370
2371
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002372 def test_short(self):
2373 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002374 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002375 it.
2376 """
2377 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04002378 server.sendall(b('x'))
2379 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002380
2381
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002382 try:
2383 memoryview
2384 except NameError:
2385 "cannot test sending memoryview without memoryview"
2386 else:
2387 def test_short_memoryview(self):
2388 """
2389 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002390 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002391 """
2392 server, client = self._loopback()
2393 server.sendall(memoryview(b('x')))
2394 self.assertEquals(client.recv(1), b('x'))
2395
2396
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002397 try:
2398 buffer
2399 except NameError:
2400 "cannot test sending buffers without buffers"
2401 else:
2402 def test_short_buffers(self):
2403 """
2404 When passed a buffer containing a small number of bytes,
2405 :py:obj:`Connection.sendall` transmits all of them.
2406 """
2407 server, client = self._loopback()
2408 server.sendall(buffer(b('x')))
2409 self.assertEquals(client.recv(1), b('x'))
2410
2411
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002412 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002413 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002414 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002415 it even if this requires multiple calls of an underlying write function.
2416 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002417 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04002418 # Should be enough, underlying SSL_write should only do 16k at a time.
2419 # On Windows, after 32k of bytes the write will block (forever - because
2420 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04002421 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002422 server.sendall(message)
2423 accum = []
2424 received = 0
2425 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04002426 data = client.recv(1024)
2427 accum.append(data)
2428 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04002429 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002430
2431
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002432 def test_closed(self):
2433 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002434 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002435 write error from the low level write call.
2436 """
2437 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04002438 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002439 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02002440 if platform == "win32":
2441 self.assertEqual(exc.args[0], ESHUTDOWN)
2442 else:
2443 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002444
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002445
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002446
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002447class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
2448 """
2449 Tests for SSL renegotiation APIs.
2450 """
2451 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002452 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002453 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002454 arguments.
2455 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002456 connection = Connection(Context(TLSv1_METHOD), None)
2457 self.assertRaises(TypeError, connection.renegotiate, None)
2458
2459
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002460 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002461 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002462 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002463 any arguments.
2464 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002465 connection = Connection(Context(TLSv1_METHOD), None)
2466 self.assertRaises(TypeError, connection.total_renegotiations, None)
2467
2468
2469 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002470 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002471 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002472 renegotiations have happened.
2473 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002474 connection = Connection(Context(TLSv1_METHOD), None)
2475 self.assertEquals(connection.total_renegotiations(), 0)
2476
2477
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002478# def test_renegotiate(self):
2479# """
2480# """
2481# server, client = self._loopback()
2482
2483# server.send("hello world")
2484# self.assertEquals(client.recv(len("hello world")), "hello world")
2485
2486# self.assertEquals(server.total_renegotiations(), 0)
2487# self.assertTrue(server.renegotiate())
2488
2489# server.setblocking(False)
2490# client.setblocking(False)
2491# while server.renegotiate_pending():
2492# client.do_handshake()
2493# server.do_handshake()
2494
2495# self.assertEquals(server.total_renegotiations(), 1)
2496
2497
2498
2499
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002500class ErrorTests(TestCase):
2501 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002502 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002503 """
2504 def test_type(self):
2505 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002506 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002507 """
2508 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05002509 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05002510
2511
2512
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002513class ConstantsTests(TestCase):
2514 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002515 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002516
2517 These are values defined by OpenSSL intended only to be used as flags to
2518 OpenSSL APIs. The only assertions it seems can be made about them is
2519 their values.
2520 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002521 # unittest.TestCase has no skip mechanism
2522 if OP_NO_QUERY_MTU is not None:
2523 def test_op_no_query_mtu(self):
2524 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002525 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002526 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002527 """
2528 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
2529 else:
2530 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002531
2532
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002533 if OP_COOKIE_EXCHANGE is not None:
2534 def test_op_cookie_exchange(self):
2535 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002536 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002537 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002538 """
2539 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
2540 else:
2541 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002542
2543
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002544 if OP_NO_TICKET is not None:
2545 def test_op_no_ticket(self):
2546 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002547 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002548 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002549 """
2550 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04002551 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002552 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05002553
2554
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002555 if OP_NO_COMPRESSION is not None:
2556 def test_op_no_compression(self):
2557 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002558 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
2559 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002560 """
2561 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
2562 else:
2563 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
2564
2565
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002566 def test_sess_cache_off(self):
2567 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002568 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
2569 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002570 """
2571 self.assertEqual(0x0, SESS_CACHE_OFF)
2572
2573
2574 def test_sess_cache_client(self):
2575 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002576 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
2577 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002578 """
2579 self.assertEqual(0x1, SESS_CACHE_CLIENT)
2580
2581
2582 def test_sess_cache_server(self):
2583 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002584 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
2585 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002586 """
2587 self.assertEqual(0x2, SESS_CACHE_SERVER)
2588
2589
2590 def test_sess_cache_both(self):
2591 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002592 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
2593 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002594 """
2595 self.assertEqual(0x3, SESS_CACHE_BOTH)
2596
2597
2598 def test_sess_cache_no_auto_clear(self):
2599 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002600 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
2601 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
2602 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002603 """
2604 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
2605
2606
2607 def test_sess_cache_no_internal_lookup(self):
2608 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002609 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
2610 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
2611 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002612 """
2613 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
2614
2615
2616 def test_sess_cache_no_internal_store(self):
2617 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002618 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
2619 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
2620 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002621 """
2622 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
2623
2624
2625 def test_sess_cache_no_internal(self):
2626 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002627 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
2628 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
2629 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002630 """
2631 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
2632
2633
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04002634
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002635class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05002636 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002637 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05002638 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002639 def _server(self, sock):
2640 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002641 Create a new server-side SSL :py:obj:`Connection` object wrapped around
2642 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002643 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002644 # Create the server side Connection. This is mostly setup boilerplate
2645 # - use TLSv1, use a particular certificate, etc.
2646 server_ctx = Context(TLSv1_METHOD)
2647 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2648 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2649 server_store = server_ctx.get_cert_store()
2650 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2651 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2652 server_ctx.check_privatekey()
2653 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002654 # Here the Connection is actually created. If None is passed as the 2nd
2655 # parameter, it indicates a memory BIO should be created.
2656 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002657 server_conn.set_accept_state()
2658 return server_conn
2659
2660
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002661 def _client(self, sock):
2662 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002663 Create a new client-side SSL :py:obj:`Connection` object wrapped around
2664 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002665 """
2666 # Now create the client side Connection. Similar boilerplate to the
2667 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002668 client_ctx = Context(TLSv1_METHOD)
2669 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2670 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2671 client_store = client_ctx.get_cert_store()
2672 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
2673 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
2674 client_ctx.check_privatekey()
2675 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002676 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002677 client_conn.set_connect_state()
2678 return client_conn
2679
2680
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002681 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002682 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002683 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002684 reading from the output of each and writing those bytes to the input of
2685 the other and in this way establish a connection and exchange
2686 application-level bytes with each other.
2687 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002688 server_conn = self._server(None)
2689 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002690
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002691 # There should be no key or nonces yet.
2692 self.assertIdentical(server_conn.master_key(), None)
2693 self.assertIdentical(server_conn.client_random(), None)
2694 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002695
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002696 # First, the handshake needs to happen. We'll deliver bytes back and
2697 # forth between the client and server until neither of them feels like
2698 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002699 self.assertIdentical(
2700 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002701
2702 # Now that the handshake is done, there should be a key and nonces.
2703 self.assertNotIdentical(server_conn.master_key(), None)
2704 self.assertNotIdentical(server_conn.client_random(), None)
2705 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04002706 self.assertEquals(server_conn.client_random(), client_conn.client_random())
2707 self.assertEquals(server_conn.server_random(), client_conn.server_random())
2708 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
2709 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002710
2711 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002712 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05002713
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002714 server_conn.write(important_message)
2715 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002716 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002717 (client_conn, important_message))
2718
2719 client_conn.write(important_message[::-1])
2720 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002721 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002722 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05002723
2724
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002725 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05002726 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002727 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002728
2729 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09002730 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002731 this test fails, there must be a problem outside the memory BIO
2732 code, as no memory BIO is involved here). Even though this isn't a
2733 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05002734 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04002735 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05002736
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002737 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05002738 client_conn.send(important_message)
2739 msg = server_conn.recv(1024)
2740 self.assertEqual(msg, important_message)
2741
2742 # Again in the other direction, just for fun.
2743 important_message = important_message[::-1]
2744 server_conn.send(important_message)
2745 msg = client_conn.recv(1024)
2746 self.assertEqual(msg, important_message)
2747
2748
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04002749 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05002750 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002751 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
2752 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05002753 """
2754 context = Context(SSLv3_METHOD)
2755 client = socket()
2756 clientSSL = Connection(context, client)
2757 self.assertRaises( TypeError, clientSSL.bio_read, 100)
2758 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04002759 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002760
2761
2762 def test_outgoingOverflow(self):
2763 """
2764 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002765 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002766 returned and that many bytes from the beginning of the input can be
2767 read from the other end of the connection.
2768 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002769 server = self._server(None)
2770 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002771
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002772 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002773
2774 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002775 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002776 # Sanity check. We're trying to test what happens when the entire
2777 # input can't be sent. If the entire input was sent, this test is
2778 # meaningless.
2779 self.assertTrue(sent < size)
2780
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002781 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002782 self.assertIdentical(receiver, server)
2783
2784 # We can rely on all of these bytes being received at once because
2785 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
2786 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002787
2788
2789 def test_shutdown(self):
2790 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002791 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
2792 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002793 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002794 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002795 server.bio_shutdown()
2796 e = self.assertRaises(Error, server.recv, 1024)
2797 # We don't want WantReadError or ZeroReturnError or anything - it's a
2798 # handshake failure.
2799 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002800
2801
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002802 def test_unexpectedEndOfFile(self):
2803 """
2804 If the connection is lost before an orderly SSL shutdown occurs,
2805 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
2806 "Unexpected EOF".
2807 """
2808 server_conn, client_conn = self._loopback()
2809 client_conn.sock_shutdown(SHUT_RDWR)
2810 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
2811 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
2812
2813
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002814 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002815 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002816 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 -04002817
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002818 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002819 before the client and server are connected to each other. This
2820 function should specify a list of CAs for the server to send to the
2821 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09002822 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002823 times.
2824 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002825 server = self._server(None)
2826 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002827 self.assertEqual(client.get_client_ca_list(), [])
2828 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002829 ctx = server.get_context()
2830 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002831 self.assertEqual(client.get_client_ca_list(), [])
2832 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002833 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002834 self.assertEqual(client.get_client_ca_list(), expected)
2835 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002836
2837
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002838 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002839 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002840 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002841 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002842 """
2843 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002844 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
2845 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
2846 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002847
2848
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002849 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002850 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002851 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002852 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09002853 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002854 after the connection is set up.
2855 """
2856 def no_ca(ctx):
2857 ctx.set_client_ca_list([])
2858 return []
2859 self._check_client_ca_list(no_ca)
2860
2861
2862 def test_set_one_ca_list(self):
2863 """
2864 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002865 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002866 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002867 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002868 X509Name after the connection is set up.
2869 """
2870 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2871 cadesc = cacert.get_subject()
2872 def single_ca(ctx):
2873 ctx.set_client_ca_list([cadesc])
2874 return [cadesc]
2875 self._check_client_ca_list(single_ca)
2876
2877
2878 def test_set_multiple_ca_list(self):
2879 """
2880 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002881 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002882 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002883 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002884 X509Names after the connection is set up.
2885 """
2886 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2887 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2888
2889 sedesc = secert.get_subject()
2890 cldesc = clcert.get_subject()
2891
2892 def multiple_ca(ctx):
2893 L = [sedesc, cldesc]
2894 ctx.set_client_ca_list(L)
2895 return L
2896 self._check_client_ca_list(multiple_ca)
2897
2898
2899 def test_reset_ca_list(self):
2900 """
2901 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09002902 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002903 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002904 """
2905 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2906 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2907 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2908
2909 cadesc = cacert.get_subject()
2910 sedesc = secert.get_subject()
2911 cldesc = clcert.get_subject()
2912
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002913 def changed_ca(ctx):
2914 ctx.set_client_ca_list([sedesc, cldesc])
2915 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002916 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002917 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002918
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002919
2920 def test_mutated_ca_list(self):
2921 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002922 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002923 afterwards, this does not affect the list of CA names sent to the
2924 client.
2925 """
2926 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2927 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2928
2929 cadesc = cacert.get_subject()
2930 sedesc = secert.get_subject()
2931
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002932 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002933 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002934 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002935 L.append(sedesc)
2936 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002937 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002938
2939
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002940 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002941 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002942 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002943 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002944 """
2945 ctx = Context(TLSv1_METHOD)
2946 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002947 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002948 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002949 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002950
2951
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002952 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002953 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002954 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09002955 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002956 """
2957 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2958 cadesc = cacert.get_subject()
2959 def single_ca(ctx):
2960 ctx.add_client_ca(cacert)
2961 return [cadesc]
2962 self._check_client_ca_list(single_ca)
2963
2964
2965 def test_multiple_add_client_ca(self):
2966 """
2967 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09002968 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002969 """
2970 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2971 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2972
2973 cadesc = cacert.get_subject()
2974 sedesc = secert.get_subject()
2975
2976 def multiple_ca(ctx):
2977 ctx.add_client_ca(cacert)
2978 ctx.add_client_ca(secert)
2979 return [cadesc, sedesc]
2980 self._check_client_ca_list(multiple_ca)
2981
2982
2983 def test_set_and_add_client_ca(self):
2984 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002985 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
2986 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002987 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002988 """
2989 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2990 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2991 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2992
2993 cadesc = cacert.get_subject()
2994 sedesc = secert.get_subject()
2995 cldesc = clcert.get_subject()
2996
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002997 def mixed_set_add_ca(ctx):
2998 ctx.set_client_ca_list([cadesc, sedesc])
2999 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003000 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003001 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003002
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003003
3004 def test_set_after_add_client_ca(self):
3005 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003006 A call to :py:obj:`Context.set_client_ca_list` after a call to
3007 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003008 call with the names specified by the latter cal.
3009 """
3010 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3011 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3012 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3013
3014 cadesc = cacert.get_subject()
3015 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003016
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003017 def set_replaces_add_ca(ctx):
3018 ctx.add_client_ca(clcert)
3019 ctx.set_client_ca_list([cadesc])
3020 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003021 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003022 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003023
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003024
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003025
3026class ConnectionBIOTests(TestCase):
3027 """
3028 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3029 """
3030 def test_wantReadError(self):
3031 """
3032 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
3033 if there are no bytes available to be read from the BIO.
3034 """
3035 ctx = Context(TLSv1_METHOD)
3036 conn = Connection(ctx, None)
3037 self.assertRaises(WantReadError, conn.bio_read, 1024)
3038
3039
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003040 def test_buffer_size(self):
3041 """
3042 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3043 number of bytes to read and return.
3044 """
3045 ctx = Context(TLSv1_METHOD)
3046 conn = Connection(ctx, None)
3047 conn.set_connect_state()
3048 try:
3049 conn.do_handshake()
3050 except WantReadError:
3051 pass
3052 data = conn.bio_read(2)
3053 self.assertEqual(2, len(data))
3054
3055
3056 if not PY3:
3057 def test_buffer_size_long(self):
3058 """
3059 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3060 :py:obj:`long` as well as :py:obj:`int`.
3061 """
3062 ctx = Context(TLSv1_METHOD)
3063 conn = Connection(ctx, None)
3064 conn.set_connect_state()
3065 try:
3066 conn.do_handshake()
3067 except WantReadError:
3068 pass
3069 data = conn.bio_read(long(2))
3070 self.assertEqual(2, len(data))
3071
3072
3073
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003074
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003075class InfoConstantTests(TestCase):
3076 """
3077 Tests for assorted constants exposed for use in info callbacks.
3078 """
3079 def test_integers(self):
3080 """
3081 All of the info constants are integers.
3082
3083 This is a very weak test. It would be nice to have one that actually
3084 verifies that as certain info events happen, the value passed to the
3085 info callback matches up with the constant exposed by OpenSSL.SSL.
3086 """
3087 for const in [
3088 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3089 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3090 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3091 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3092 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
3093 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
3094
3095 self.assertTrue(isinstance(const, int))
3096
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003097
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003098if __name__ == '__main__':
3099 main()