blob: b8271e203c9b396c1bcd4e8f19bf5f4a7e2f6c8a [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 Calderonef73a3cb2014-02-09 08:49:06 -0500397 if not PY3:
398 def test_use_privatekey_file_long(self):
399 """
400 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
401 filetype of type :py:obj:`long` as well as :py:obj:`int`.
402 """
403 pemfile = self.mktemp()
404
405 key = PKey()
406 key.generate_key(TYPE_RSA, 128)
407
408 with open(pemfile, "wt") as pem:
409 pem.write(
410 dump_privatekey(FILETYPE_PEM, key).decode("ascii"))
411
412 ctx = Context(TLSv1_METHOD)
413 ctx.use_privatekey_file(pemfile, long(FILETYPE_PEM))
414
415
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800416 def test_use_certificate_wrong_args(self):
417 """
418 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
419 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as an
420 argument.
421 """
422 ctx = Context(TLSv1_METHOD)
423 self.assertRaises(TypeError, ctx.use_certificate)
424 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
425 self.assertRaises(TypeError, ctx.use_certificate, X509(), "hello, world")
426
427
428 def test_use_certificate_uninitialized(self):
429 """
430 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
431 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
432 initialized (ie, which does not actually have any certificate data).
433 """
434 ctx = Context(TLSv1_METHOD)
435 self.assertRaises(Error, ctx.use_certificate, X509())
436
437
438 def test_use_certificate(self):
439 """
440 :py:obj:`Context.use_certificate` sets the certificate which will be
441 used to identify connections created using the context.
442 """
443 # TODO
444 # Hard to assert anything. But we could set a privatekey then ask
445 # OpenSSL if the cert and key agree using check_privatekey. Then as
446 # long as check_privatekey works right we're good...
447 ctx = Context(TLSv1_METHOD)
448 ctx.use_certificate(load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
449
450
451 def test_use_certificate_file_wrong_args(self):
452 """
453 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
454 called with zero arguments or more than two arguments, or if the first
455 argument is not a byte string or the second argumnent is not an integer.
456 """
457 ctx = Context(TLSv1_METHOD)
458 self.assertRaises(TypeError, ctx.use_certificate_file)
459 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile", object())
460 self.assertRaises(
461 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM, object())
462 self.assertRaises(
463 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
464 self.assertRaises(
465 TypeError, ctx.use_certificate_file, b"somefile", object())
466
467
468 def test_use_certificate_file_missing(self):
469 """
470 :py:obj:`Context.use_certificate_file` raises
471 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does not
472 exist.
473 """
474 ctx = Context(TLSv1_METHOD)
475 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
476
477
478 def test_use_certificate_file(self):
479 """
480 :py:obj:`Context.use_certificate` sets the certificate which will be
481 used to identify connections created using the context.
482 """
483 # TODO
484 # Hard to assert anything. But we could set a privatekey then ask
485 # OpenSSL if the cert and key agree using check_privatekey. Then as
486 # long as check_privatekey works right we're good...
487 pem_filename = self.mktemp()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500488 with open(pem_filename, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800489 pem_file.write(cleartextCertificatePEM)
490
491 ctx = Context(TLSv1_METHOD)
492 ctx.use_certificate_file(pem_filename)
493
494
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500495 if not PY3:
496 def test_use_certificate_file_long(self):
497 """
498 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
499 filetype of type :py:obj:`long` as well as :py:obj:`int`.
500 """
501 pem_filename = self.mktemp()
502 with open(pem_filename, "wb") as pem_file:
503 pem_file.write(cleartextCertificatePEM)
504
505 ctx = Context(TLSv1_METHOD)
506 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
507
508
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400509 def test_set_app_data_wrong_args(self):
510 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900511 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called with other than
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400512 one argument.
513 """
514 context = Context(TLSv1_METHOD)
515 self.assertRaises(TypeError, context.set_app_data)
516 self.assertRaises(TypeError, context.set_app_data, None, None)
517
518
519 def test_get_app_data_wrong_args(self):
520 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900521 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400522 arguments.
523 """
524 context = Context(TLSv1_METHOD)
525 self.assertRaises(TypeError, context.get_app_data, None)
526
527
528 def test_app_data(self):
529 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900530 :py:obj:`Context.set_app_data` stores an object for later retrieval using
531 :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400532 """
533 app_data = object()
534 context = Context(TLSv1_METHOD)
535 context.set_app_data(app_data)
536 self.assertIdentical(context.get_app_data(), app_data)
537
538
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400539 def test_set_options_wrong_args(self):
540 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900541 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with the wrong
542 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400543 """
544 context = Context(TLSv1_METHOD)
545 self.assertRaises(TypeError, context.set_options)
546 self.assertRaises(TypeError, context.set_options, None)
547 self.assertRaises(TypeError, context.set_options, 1, None)
548
549
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500550 def test_set_options(self):
551 """
552 :py:obj:`Context.set_options` returns the new options value.
553 """
554 context = Context(TLSv1_METHOD)
555 options = context.set_options(OP_NO_SSLv2)
556 self.assertTrue(OP_NO_SSLv2 & options)
557
558
559 if not PY3:
560 def test_set_options_long(self):
561 """
562 On Python 2 :py:obj:`Context.set_options` accepts values of type
563 :py:obj:`long` as well as :py:obj:`int`.
564 """
565 context = Context(TLSv1_METHOD)
566 options = context.set_options(long(OP_NO_SSLv2))
567 self.assertTrue(OP_NO_SSLv2 & options)
568
569
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300570 def test_set_mode_wrong_args(self):
571 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400572 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with the wrong
573 number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300574 """
575 context = Context(TLSv1_METHOD)
576 self.assertRaises(TypeError, context.set_mode)
577 self.assertRaises(TypeError, context.set_mode, None)
578 self.assertRaises(TypeError, context.set_mode, 1, None)
579
580
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400581 if MODE_RELEASE_BUFFERS is not None:
582 def test_set_mode(self):
583 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400584 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the newly
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400585 set mode.
586 """
587 context = Context(TLSv1_METHOD)
588 self.assertTrue(
589 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500590
591 if not PY3:
592 def test_set_mode_long(self):
593 """
594 On Python 2 :py:obj:`Context.set_mode` accepts values of type
595 :py:obj:`long` as well as :py:obj:`int`.
596 """
597 context = Context(TLSv1_METHOD)
598 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
599 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400600 else:
601 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
602
603
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400604 def test_set_timeout_wrong_args(self):
605 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900606 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with the wrong
607 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400608 """
609 context = Context(TLSv1_METHOD)
610 self.assertRaises(TypeError, context.set_timeout)
611 self.assertRaises(TypeError, context.set_timeout, None)
612 self.assertRaises(TypeError, context.set_timeout, 1, None)
613
614
615 def test_get_timeout_wrong_args(self):
616 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900617 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400618 """
619 context = Context(TLSv1_METHOD)
620 self.assertRaises(TypeError, context.get_timeout, None)
621
622
623 def test_timeout(self):
624 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900625 :py:obj:`Context.set_timeout` sets the session timeout for all connections
626 created using the context object. :py:obj:`Context.get_timeout` retrieves this
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400627 value.
628 """
629 context = Context(TLSv1_METHOD)
630 context.set_timeout(1234)
631 self.assertEquals(context.get_timeout(), 1234)
632
633
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500634 if not PY3:
635 def test_timeout_long(self):
636 """
637 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
638 `long` as well as int.
639 """
640 context = Context(TLSv1_METHOD)
641 context.set_timeout(long(1234))
642 self.assertEquals(context.get_timeout(), 1234)
643
644
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400645 def test_set_verify_depth_wrong_args(self):
646 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900647 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called with the wrong
648 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400649 """
650 context = Context(TLSv1_METHOD)
651 self.assertRaises(TypeError, context.set_verify_depth)
652 self.assertRaises(TypeError, context.set_verify_depth, None)
653 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
654
655
656 def test_get_verify_depth_wrong_args(self):
657 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900658 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400659 """
660 context = Context(TLSv1_METHOD)
661 self.assertRaises(TypeError, context.get_verify_depth, None)
662
663
664 def test_verify_depth(self):
665 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900666 :py:obj:`Context.set_verify_depth` sets the number of certificates in a chain
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400667 to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900668 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400669 """
670 context = Context(TLSv1_METHOD)
671 context.set_verify_depth(11)
672 self.assertEquals(context.get_verify_depth(), 11)
673
674
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500675 if not PY3:
676 def test_verify_depth_long(self):
677 """
678 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
679 type `long` as well as int.
680 """
681 context = Context(TLSv1_METHOD)
682 context.set_verify_depth(long(11))
683 self.assertEquals(context.get_verify_depth(), 11)
684
685
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400686 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400687 """
688 Write a new private key out to a new file, encrypted using the given
689 passphrase. Return the path to the new file.
690 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400691 key = PKey()
692 key.generate_key(TYPE_RSA, 128)
693 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400694 fObj = open(pemFile, 'w')
695 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
696 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400697 fObj.close()
698 return pemFile
699
700
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400701 def test_set_passwd_cb_wrong_args(self):
702 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900703 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called with the
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400704 wrong arguments or with a non-callable first argument.
705 """
706 context = Context(TLSv1_METHOD)
707 self.assertRaises(TypeError, context.set_passwd_cb)
708 self.assertRaises(TypeError, context.set_passwd_cb, None)
709 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
710
711
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400712 def test_set_passwd_cb(self):
713 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900714 :py:obj:`Context.set_passwd_cb` accepts a callable which will be invoked when
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400715 a private key is loaded from an encrypted PEM.
716 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400717 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400718 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400719 calledWith = []
720 def passphraseCallback(maxlen, verify, extra):
721 calledWith.append((maxlen, verify, extra))
722 return passphrase
723 context = Context(TLSv1_METHOD)
724 context.set_passwd_cb(passphraseCallback)
725 context.use_privatekey_file(pemFile)
726 self.assertTrue(len(calledWith), 1)
727 self.assertTrue(isinstance(calledWith[0][0], int))
728 self.assertTrue(isinstance(calledWith[0][1], int))
729 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400730
731
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400732 def test_passwd_callback_exception(self):
733 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900734 :py:obj:`Context.use_privatekey_file` propagates any exception raised by the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400735 passphrase callback.
736 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400737 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400738 def passphraseCallback(maxlen, verify, extra):
739 raise RuntimeError("Sorry, I am a fail.")
740
741 context = Context(TLSv1_METHOD)
742 context.set_passwd_cb(passphraseCallback)
743 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
744
745
746 def test_passwd_callback_false(self):
747 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900748 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400749 passphrase callback returns a false value.
750 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400751 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400752 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500753 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400754
755 context = Context(TLSv1_METHOD)
756 context.set_passwd_cb(passphraseCallback)
757 self.assertRaises(Error, context.use_privatekey_file, pemFile)
758
759
760 def test_passwd_callback_non_string(self):
761 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900762 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400763 passphrase callback returns a true non-string value.
764 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400765 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400766 def passphraseCallback(maxlen, verify, extra):
767 return 10
768
769 context = Context(TLSv1_METHOD)
770 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800771 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400772
773
774 def test_passwd_callback_too_long(self):
775 """
776 If the passphrase returned by the passphrase callback returns a string
777 longer than the indicated maximum length, it is truncated.
778 """
779 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400780 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400781 pemFile = self._write_encrypted_pem(passphrase)
782 def passphraseCallback(maxlen, verify, extra):
783 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400784 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400785
786 context = Context(TLSv1_METHOD)
787 context.set_passwd_cb(passphraseCallback)
788 # This shall succeed because the truncated result is the correct
789 # passphrase.
790 context.use_privatekey_file(pemFile)
791
792
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400793 def test_set_info_callback(self):
794 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900795 :py:obj:`Context.set_info_callback` accepts a callable which will be invoked
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400796 when certain information about an SSL connection is available.
797 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500798 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400799
800 clientSSL = Connection(Context(TLSv1_METHOD), client)
801 clientSSL.set_connect_state()
802
803 called = []
804 def info(conn, where, ret):
805 called.append((conn, where, ret))
806 context = Context(TLSv1_METHOD)
807 context.set_info_callback(info)
808 context.use_certificate(
809 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
810 context.use_privatekey(
811 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
812
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400813 serverSSL = Connection(context, server)
814 serverSSL.set_accept_state()
815
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500816 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400817
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500818 # The callback must always be called with a Connection instance as the
819 # first argument. It would probably be better to split this into
820 # separate tests for client and server side info callbacks so we could
821 # assert it is called with the right Connection instance. It would
822 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500823 notConnections = [
824 conn for (conn, where, ret) in called
825 if not isinstance(conn, Connection)]
826 self.assertEqual(
827 [], notConnections,
828 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400829
830
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400831 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400832 """
833 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400834 its :py:obj:`load_verify_locations` method with the given arguments.
835 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400836 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500837 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400838
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400839 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400840 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400841 # Require that the server certificate verify properly or the
842 # connection will fail.
843 clientContext.set_verify(
844 VERIFY_PEER,
845 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
846
847 clientSSL = Connection(clientContext, client)
848 clientSSL.set_connect_state()
849
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400850 serverContext = Context(TLSv1_METHOD)
851 serverContext.use_certificate(
852 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
853 serverContext.use_privatekey(
854 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
855
856 serverSSL = Connection(serverContext, server)
857 serverSSL.set_accept_state()
858
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400859 # Without load_verify_locations above, the handshake
860 # will fail:
861 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
862 # 'certificate verify failed')]
863 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400864
865 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400866 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400867
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500868
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400869 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400870 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400871 Verify that if path to a file containing a certificate is passed to
872 ``Context.load_verify_locations`` for the ``cafile`` parameter, that
873 certificate is used as a trust root for the purposes of verifying
874 connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400875 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400876 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400877 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400878 fObj.close()
879
880 self._load_verify_locations_test(cafile)
881
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400882
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400883 def test_load_verify_bytes_cafile(self):
884 """
885 :py:obj:`Context.load_verify_locations` accepts a file name as a
886 ``bytes`` instance and uses the certificates within for verification
887 purposes.
888 """
889 cafile = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
890 self._load_verify_cafile(cafile)
891
892
893 def test_load_verify_unicode_cafile(self):
894 """
895 :py:obj:`Context.load_verify_locations` accepts a file name as a
896 ``unicode`` instance and uses the certificates within for verification
897 purposes.
898 """
899 cafile = self.mktemp() + NON_ASCII
900 self._load_verify_cafile(cafile)
901
902
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400903 def test_load_verify_invalid_file(self):
904 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900905 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when passed a
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400906 non-existent cafile.
907 """
908 clientContext = Context(TLSv1_METHOD)
909 self.assertRaises(
910 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400911
912
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400913 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400914 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400915 Verify that if path to a directory containing certificate files is
916 passed to ``Context.load_verify_locations`` for the ``capath``
917 parameter, those certificates are used as trust roots for the purposes
918 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400919 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400920 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400921 # Hash values computed manually with c_rehash to avoid depending on
922 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
923 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500924 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400925 cafile = join(capath, name)
926 fObj = open(cafile, 'w')
927 fObj.write(cleartextCertificatePEM.decode('ascii'))
928 fObj.close()
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400929
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400930 self._load_verify_locations_test(None, capath)
931
932
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400933 def test_load_verify_directory_bytes_capath(self):
934 """
935 :py:obj:`Context.load_verify_locations` accepts a directory name as a
936 ``bytes`` instance and uses the certificates within for verification
937 purposes.
938 """
939 self._load_verify_directory_locations_capath(
940 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
941 )
942
943
944 def test_load_verify_directory_unicode_capath(self):
945 """
946 :py:obj:`Context.load_verify_locations` accepts a directory name as a
947 ``unicode`` instance and uses the certificates within for verification
948 purposes.
949 """
950 self._load_verify_directory_locations_capath(self.mktemp() + NON_ASCII)
951
952
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400953 def test_load_verify_locations_wrong_args(self):
954 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900955 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if called with
956 the wrong number of arguments or with non-:py:obj:`str` arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400957 """
958 context = Context(TLSv1_METHOD)
959 self.assertRaises(TypeError, context.load_verify_locations)
960 self.assertRaises(TypeError, context.load_verify_locations, object())
961 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
962 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
963
964
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400965 if platform == "win32":
966 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400967 "See LP#404343 and LP#404344."
968 else:
969 def test_set_default_verify_paths(self):
970 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900971 :py:obj:`Context.set_default_verify_paths` causes the platform-specific CA
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400972 certificate locations to be used for verification purposes.
973 """
974 # Testing this requires a server with a certificate signed by one of
975 # the CAs in the platform CA location. Getting one of those costs
976 # money. Fortunately (or unfortunately, depending on your
977 # perspective), it's easy to think of a public server on the
978 # internet which has such a certificate. Connecting to the network
979 # in a unit test is bad, but it's the only way I can think of to
980 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400981
Alex Gaynorb586da32014-11-15 09:22:21 -0800982 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
983 context = Context(TLSv1_METHOD)
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400984 context.set_default_verify_paths()
985 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +0200986 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400987 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400988
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400989 client = socket()
990 client.connect(('verisign.com', 443))
991 clientSSL = Connection(context, client)
992 clientSSL.set_connect_state()
993 clientSSL.do_handshake()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500994 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400995 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400996
997
998 def test_set_default_verify_paths_signature(self):
999 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001000 :py:obj:`Context.set_default_verify_paths` takes no arguments and raises
1001 :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001002 """
1003 context = Context(TLSv1_METHOD)
1004 self.assertRaises(TypeError, context.set_default_verify_paths, None)
1005 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
1006 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001007
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001008
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001009 def test_add_extra_chain_cert_invalid_cert(self):
1010 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001011 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if called with
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001012 other than one argument or if called with an object which is not an
Jonathan Ballet648875f2011-07-16 14:14:58 +09001013 instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001014 """
1015 context = Context(TLSv1_METHOD)
1016 self.assertRaises(TypeError, context.add_extra_chain_cert)
1017 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
1018 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
1019
1020
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001021 def _handshake_test(self, serverContext, clientContext):
1022 """
1023 Verify that a client and server created with the given contexts can
1024 successfully handshake and communicate.
1025 """
1026 serverSocket, clientSocket = socket_pair()
1027
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001028 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001029 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001030
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001031 client = Connection(clientContext, clientSocket)
1032 client.set_connect_state()
1033
1034 # Make them talk to each other.
1035 # self._interactInMemory(client, server)
1036 for i in range(3):
1037 for s in [client, server]:
1038 try:
1039 s.do_handshake()
1040 except WantReadError:
1041 pass
1042
1043
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001044 def test_set_verify_callback_connection_argument(self):
1045 """
1046 The first argument passed to the verify callback is the
1047 :py:class:`Connection` instance for which verification is taking place.
1048 """
1049 serverContext = Context(TLSv1_METHOD)
1050 serverContext.use_privatekey(
1051 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1052 serverContext.use_certificate(
1053 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1054 serverConnection = Connection(serverContext, None)
1055
1056 class VerifyCallback(object):
1057 def callback(self, connection, *args):
1058 self.connection = connection
1059 return 1
1060
1061 verify = VerifyCallback()
1062 clientContext = Context(TLSv1_METHOD)
1063 clientContext.set_verify(VERIFY_PEER, verify.callback)
1064 clientConnection = Connection(clientContext, None)
1065 clientConnection.set_connect_state()
1066
1067 self._handshakeInMemory(clientConnection, serverConnection)
1068
1069 self.assertIdentical(verify.connection, clientConnection)
1070
1071
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001072 def test_set_verify_callback_exception(self):
1073 """
1074 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1075 exception, verification fails and the exception is propagated to the
1076 caller of :py:obj:`Connection.do_handshake`.
1077 """
1078 serverContext = Context(TLSv1_METHOD)
1079 serverContext.use_privatekey(
1080 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1081 serverContext.use_certificate(
1082 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1083
1084 clientContext = Context(TLSv1_METHOD)
1085 def verify_callback(*args):
1086 raise Exception("silly verify failure")
1087 clientContext.set_verify(VERIFY_PEER, verify_callback)
1088
1089 exc = self.assertRaises(
1090 Exception, self._handshake_test, serverContext, clientContext)
1091 self.assertEqual("silly verify failure", str(exc))
1092
1093
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001094 def test_add_extra_chain_cert(self):
1095 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001096 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509` instance to add to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001097 the certificate chain.
1098
Jonathan Ballet648875f2011-07-16 14:14:58 +09001099 See :py:obj:`_create_certificate_chain` for the details of the certificate
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001100 chain tested.
1101
1102 The chain is tested by starting a server with scert and connecting
1103 to it with a client which trusts cacert and requires verification to
1104 succeed.
1105 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001106 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001107 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1108
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001109 # Dump the CA certificate to a file because that's the only way to load
1110 # it as a trusted CA in the client context.
1111 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001112 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001113 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001114 fObj.close()
1115
1116 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001117 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001118 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001119 fObj.close()
1120
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001121 # Create the server context
1122 serverContext = Context(TLSv1_METHOD)
1123 serverContext.use_privatekey(skey)
1124 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001125 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001126 serverContext.add_extra_chain_cert(icert)
1127
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001128 # Create the client
1129 clientContext = Context(TLSv1_METHOD)
1130 clientContext.set_verify(
1131 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001132 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001133
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001134 # Try it out.
1135 self._handshake_test(serverContext, clientContext)
1136
1137
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001138 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001139 """
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001140 Verify that :py:obj:`Context.use_certificate_chain_file` reads a
1141 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001142
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001143 The chain is tested by starting a server with scert and connecting to
1144 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001145 succeed.
1146 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001147 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001148 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1149
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001150 makedirs(certdir)
1151
1152 if isinstance(certdir, binary_type):
1153 chainFile = join(certdir, b("chain.pem"))
1154 caFile = join(certdir, b("ca.pem"))
1155 else:
1156 chainFile = join(certdir, u"chain.pem")
1157 caFile = join(certdir, u"ca.pem")
1158
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001159 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001160 with open(chainFile, 'wb') as fObj:
1161 # Most specific to least general.
1162 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1163 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1164 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1165
1166 with open(caFile, 'w') as fObj:
1167 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001168
1169 serverContext = Context(TLSv1_METHOD)
1170 serverContext.use_certificate_chain_file(chainFile)
1171 serverContext.use_privatekey(skey)
1172
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001173 clientContext = Context(TLSv1_METHOD)
1174 clientContext.set_verify(
1175 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001176 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001177
1178 self._handshake_test(serverContext, clientContext)
1179
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001180
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001181 def test_use_certificate_chain_file_bytes(self):
1182 """
1183 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1184 an instance of ``bytes``) to specify additional certificates to use to
1185 construct and verify a trust chain.
1186 """
1187 self._use_certificate_chain_file_test(
1188 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
1189 )
1190
1191
1192 def test_use_certificate_chain_file_unicode(self):
1193 """
1194 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1195 an instance of ``unicode``) to specify additional certificates to use
1196 to construct and verify a trust chain.
1197 """
1198 self._use_certificate_chain_file_test(
1199 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
1200 )
1201
1202
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001203 def test_use_certificate_chain_file_wrong_args(self):
1204 """
1205 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1206 if passed zero or more than one argument or when passed a non-byte
1207 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error` when
1208 passed a bad chain file name (for example, the name of a file which does
1209 not exist).
1210 """
1211 context = Context(TLSv1_METHOD)
1212 self.assertRaises(TypeError, context.use_certificate_chain_file)
1213 self.assertRaises(TypeError, context.use_certificate_chain_file, object())
1214 self.assertRaises(TypeError, context.use_certificate_chain_file, b"foo", object())
1215
1216 self.assertRaises(Error, context.use_certificate_chain_file, self.mktemp())
1217
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001218 # XXX load_client_ca
1219 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001220
1221 def test_get_verify_mode_wrong_args(self):
1222 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001223 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001224 arguments.
1225 """
1226 context = Context(TLSv1_METHOD)
1227 self.assertRaises(TypeError, context.get_verify_mode, None)
1228
1229
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001230 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001231 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001232 :py:obj:`Context.get_verify_mode` returns the verify mode flags previously
1233 passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001234 """
1235 context = Context(TLSv1_METHOD)
1236 self.assertEquals(context.get_verify_mode(), 0)
1237 context.set_verify(
1238 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1239 self.assertEquals(
1240 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1241
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001242
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001243 if not PY3:
1244 def test_set_verify_mode_long(self):
1245 """
1246 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1247 type :py:obj:`long` as well as :py:obj:`int`.
1248 """
1249 context = Context(TLSv1_METHOD)
1250 self.assertEquals(context.get_verify_mode(), 0)
1251 context.set_verify(
1252 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None)
1253 self.assertEquals(
1254 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1255
1256
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001257 def test_load_tmp_dh_wrong_args(self):
1258 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001259 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
1260 number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001261 """
1262 context = Context(TLSv1_METHOD)
1263 self.assertRaises(TypeError, context.load_tmp_dh)
1264 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1265 self.assertRaises(TypeError, context.load_tmp_dh, object())
1266
1267
1268 def test_load_tmp_dh_missing_file(self):
1269 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001270 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the specified file
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001271 does not exist.
1272 """
1273 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001274 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001275
1276
1277 def test_load_tmp_dh(self):
1278 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001279 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001280 specified file.
1281 """
1282 context = Context(TLSv1_METHOD)
1283 dhfilename = self.mktemp()
1284 dhfile = open(dhfilename, "w")
1285 dhfile.write(dhparam)
1286 dhfile.close()
1287 context.load_tmp_dh(dhfilename)
1288 # XXX What should I assert here? -exarkun
1289
1290
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001291 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001292 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001293 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001294 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001295 """
1296 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001297 for curve in get_elliptic_curves():
1298 # The only easily "assertable" thing is that it does not raise an
1299 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001300 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001301
1302
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001303 def test_set_cipher_list_bytes(self):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001304 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001305 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
1306 ciphers which connections created with the context object will be able
1307 to choose from.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001308 """
1309 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001310 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001311 conn = Connection(context, None)
1312 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001313
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001314
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001315 def test_set_cipher_list_text(self):
1316 """
1317 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
1318 the ciphers which connections created with the context object will be
1319 able to choose from.
1320 """
1321 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -05001322 context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001323 conn = Connection(context, None)
1324 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
1325
1326
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001327 def test_set_cipher_list_wrong_args(self):
1328 """
Jean-Paul Calderone17044832014-01-18 10:20:11 -05001329 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
1330 passed zero arguments or more than one argument or when passed a
1331 non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001332 passed an incorrect cipher list string.
1333 """
1334 context = Context(TLSv1_METHOD)
1335 self.assertRaises(TypeError, context.set_cipher_list)
1336 self.assertRaises(TypeError, context.set_cipher_list, object())
1337 self.assertRaises(TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object())
1338
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001339 self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001340
1341
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001342 def test_set_session_cache_mode_wrong_args(self):
1343 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001344 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1345 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001346 """
1347 context = Context(TLSv1_METHOD)
1348 self.assertRaises(TypeError, context.set_session_cache_mode)
1349 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1350
1351
1352 def test_get_session_cache_mode_wrong_args(self):
1353 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001354 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1355 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001356 """
1357 context = Context(TLSv1_METHOD)
1358 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1359
1360
1361 def test_session_cache_mode(self):
1362 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001363 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1364 cached. The setting can be retrieved via
1365 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001366 """
1367 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001368 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001369 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1370 self.assertEqual(SESS_CACHE_OFF, off)
1371 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1372
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001373 if not PY3:
1374 def test_session_cache_mode_long(self):
1375 """
1376 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1377 of type :py:obj:`long` as well as :py:obj:`int`.
1378 """
1379 context = Context(TLSv1_METHOD)
1380 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1381 self.assertEqual(
1382 SESS_CACHE_BOTH, context.get_session_cache_mode())
1383
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001384
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001385 def test_get_cert_store(self):
1386 """
1387 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store` instance.
1388 """
1389 context = Context(TLSv1_METHOD)
1390 store = context.get_cert_store()
1391 self.assertIsInstance(store, X509Store)
1392
1393
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001394
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001395class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1396 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001397 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
1398 :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001399 """
1400 def test_wrong_args(self):
1401 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001402 :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001403 with other than one argument.
1404 """
1405 context = Context(TLSv1_METHOD)
1406 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1407 self.assertRaises(
1408 TypeError, context.set_tlsext_servername_callback, 1, 2)
1409
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001410
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001411 def test_old_callback_forgotten(self):
1412 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001413 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001414 callback, the one it replaces is dereferenced.
1415 """
1416 def callback(connection):
1417 pass
1418
1419 def replacement(connection):
1420 pass
1421
1422 context = Context(TLSv1_METHOD)
1423 context.set_tlsext_servername_callback(callback)
1424
1425 tracker = ref(callback)
1426 del callback
1427
1428 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001429
1430 # One run of the garbage collector happens to work on CPython. PyPy
1431 # doesn't collect the underlying object until a second run for whatever
1432 # reason. That's fine, it still demonstrates our code has properly
1433 # dropped the reference.
1434 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001435 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001436
1437 callback = tracker()
1438 if callback is not None:
1439 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001440 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001441 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001442
1443
1444 def test_no_servername(self):
1445 """
1446 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001447 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
1448 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001449 """
1450 args = []
1451 def servername(conn):
1452 args.append((conn, conn.get_servername()))
1453 context = Context(TLSv1_METHOD)
1454 context.set_tlsext_servername_callback(servername)
1455
1456 # Lose our reference to it. The Context is responsible for keeping it
1457 # alive now.
1458 del servername
1459 collect()
1460
1461 # Necessary to actually accept the connection
1462 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1463 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1464
1465 # Do a little connection to trigger the logic
1466 server = Connection(context, None)
1467 server.set_accept_state()
1468
1469 client = Connection(Context(TLSv1_METHOD), None)
1470 client.set_connect_state()
1471
1472 self._interactInMemory(server, client)
1473
1474 self.assertEqual([(server, None)], args)
1475
1476
1477 def test_servername(self):
1478 """
1479 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +09001480 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
1481 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001482 """
1483 args = []
1484 def servername(conn):
1485 args.append((conn, conn.get_servername()))
1486 context = Context(TLSv1_METHOD)
1487 context.set_tlsext_servername_callback(servername)
1488
1489 # Necessary to actually accept the connection
1490 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1491 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1492
1493 # Do a little connection to trigger the logic
1494 server = Connection(context, None)
1495 server.set_accept_state()
1496
1497 client = Connection(Context(TLSv1_METHOD), None)
1498 client.set_connect_state()
1499 client.set_tlsext_host_name(b("foo1.example.com"))
1500
1501 self._interactInMemory(server, client)
1502
1503 self.assertEqual([(server, b("foo1.example.com"))], args)
1504
1505
1506
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001507class SessionTests(TestCase):
1508 """
1509 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1510 """
1511 def test_construction(self):
1512 """
1513 :py:class:`Session` can be constructed with no arguments, creating a new
1514 instance of that type.
1515 """
1516 new_session = Session()
1517 self.assertTrue(isinstance(new_session, Session))
1518
1519
1520 def test_construction_wrong_args(self):
1521 """
1522 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
1523 is raised.
1524 """
1525 self.assertRaises(TypeError, Session, 123)
1526 self.assertRaises(TypeError, Session, "hello")
1527 self.assertRaises(TypeError, Session, object())
1528
1529
1530
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001531class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05001532 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001533 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001534 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001535 # XXX get_peer_certificate -> None
1536 # XXX sock_shutdown
1537 # XXX master_key -> TypeError
1538 # XXX server_random -> TypeError
1539 # XXX state_string
1540 # XXX connect -> TypeError
1541 # XXX connect_ex -> TypeError
1542 # XXX set_connect_state -> TypeError
1543 # XXX set_accept_state -> TypeError
1544 # XXX renegotiate_pending
1545 # XXX do_handshake -> TypeError
1546 # XXX bio_read -> TypeError
1547 # XXX recv -> TypeError
1548 # XXX send -> TypeError
1549 # XXX bio_write -> TypeError
1550
Rick Deane15b1472009-07-09 15:53:42 -05001551 def test_type(self):
1552 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001553 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001554 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05001555 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001556 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05001557 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001558 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05001559
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001560
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001561 def test_get_context(self):
1562 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001563 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
1564 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001565 """
1566 context = Context(TLSv1_METHOD)
1567 connection = Connection(context, None)
1568 self.assertIdentical(connection.get_context(), context)
1569
1570
1571 def test_get_context_wrong_args(self):
1572 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001573 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001574 arguments.
1575 """
1576 connection = Connection(Context(TLSv1_METHOD), None)
1577 self.assertRaises(TypeError, connection.get_context, None)
1578
1579
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001580 def test_set_context_wrong_args(self):
1581 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001582 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
1583 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001584 than 1.
1585 """
1586 ctx = Context(TLSv1_METHOD)
1587 connection = Connection(ctx, None)
1588 self.assertRaises(TypeError, connection.set_context)
1589 self.assertRaises(TypeError, connection.set_context, object())
1590 self.assertRaises(TypeError, connection.set_context, "hello")
1591 self.assertRaises(TypeError, connection.set_context, 1)
1592 self.assertRaises(TypeError, connection.set_context, 1, 2)
1593 self.assertRaises(
1594 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
1595 self.assertIdentical(ctx, connection.get_context())
1596
1597
1598 def test_set_context(self):
1599 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001600 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001601 for the connection.
1602 """
1603 original = Context(SSLv23_METHOD)
1604 replacement = Context(TLSv1_METHOD)
1605 connection = Connection(original, None)
1606 connection.set_context(replacement)
1607 self.assertIdentical(replacement, connection.get_context())
1608 # Lose our references to the contexts, just in case the Connection isn't
1609 # properly managing its own contributions to their reference counts.
1610 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001611 collect()
1612
1613
1614 def test_set_tlsext_host_name_wrong_args(self):
1615 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001616 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001617 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09001618 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001619 """
1620 conn = Connection(Context(TLSv1_METHOD), None)
1621 self.assertRaises(TypeError, conn.set_tlsext_host_name)
1622 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
1623 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
1624 self.assertRaises(
1625 TypeError, conn.set_tlsext_host_name, b("with\0null"))
1626
1627 if version_info >= (3,):
1628 # On Python 3.x, don't accidentally implicitly convert from text.
1629 self.assertRaises(
1630 TypeError,
1631 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001632
1633
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001634 def test_get_servername_wrong_args(self):
1635 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001636 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001637 arguments.
1638 """
1639 connection = Connection(Context(TLSv1_METHOD), None)
1640 self.assertRaises(TypeError, connection.get_servername, object())
1641 self.assertRaises(TypeError, connection.get_servername, 1)
1642 self.assertRaises(TypeError, connection.get_servername, "hello")
1643
1644
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001645 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001646 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001647 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001648 immediate read.
1649 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001650 connection = Connection(Context(TLSv1_METHOD), None)
1651 self.assertEquals(connection.pending(), 0)
1652
1653
1654 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001655 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001656 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001657 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001658 connection = Connection(Context(TLSv1_METHOD), None)
1659 self.assertRaises(TypeError, connection.pending, None)
1660
1661
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001662 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001663 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001664 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001665 argument or with the wrong number of arguments.
1666 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001667 connection = Connection(Context(TLSv1_METHOD), socket())
1668 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001669 self.assertRaises(TypeError, connection.connect)
1670 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001671
1672
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001673 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001674 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001675 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001676 connect method raises it.
1677 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001678 client = socket()
1679 context = Context(TLSv1_METHOD)
1680 clientSSL = Connection(context, client)
1681 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04001682 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001683
1684
1685 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001686 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001687 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001688 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001689 port = socket()
1690 port.bind(('', 0))
1691 port.listen(3)
1692
1693 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001694 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
1695 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001696
1697
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001698 if platform == "darwin":
1699 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
1700 else:
1701 def test_connect_ex(self):
1702 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001703 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001704 errno instead of raising an exception.
1705 """
1706 port = socket()
1707 port.bind(('', 0))
1708 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001709
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001710 clientSSL = Connection(Context(TLSv1_METHOD), socket())
1711 clientSSL.setblocking(False)
1712 result = clientSSL.connect_ex(port.getsockname())
1713 expected = (EINPROGRESS, EWOULDBLOCK)
1714 self.assertTrue(
1715 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001716
1717
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001718 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001719 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001720 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001721 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001722 connection = Connection(Context(TLSv1_METHOD), socket())
1723 self.assertRaises(TypeError, connection.accept, None)
1724
1725
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001726 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001727 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001728 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
1729 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001730 connection originated from.
1731 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001732 ctx = Context(TLSv1_METHOD)
1733 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1734 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001735 port = socket()
1736 portSSL = Connection(ctx, port)
1737 portSSL.bind(('', 0))
1738 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001739
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001740 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001741
1742 # Calling portSSL.getsockname() here to get the server IP address sounds
1743 # great, but frequently fails on Windows.
1744 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001745
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001746 serverSSL, address = portSSL.accept()
1747
1748 self.assertTrue(isinstance(serverSSL, Connection))
1749 self.assertIdentical(serverSSL.get_context(), ctx)
1750 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001751
1752
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001753 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001754 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001755 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001756 number of arguments or with arguments other than integers.
1757 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001758 connection = Connection(Context(TLSv1_METHOD), None)
1759 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04001760 self.assertRaises(TypeError, connection.get_shutdown, None)
1761 self.assertRaises(TypeError, connection.set_shutdown)
1762 self.assertRaises(TypeError, connection.set_shutdown, None)
1763 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001764
1765
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001766 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001767 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001768 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001769 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001770 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001771 self.assertFalse(server.shutdown())
1772 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001773 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001774 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
1775 client.shutdown()
1776 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
1777 self.assertRaises(ZeroReturnError, server.recv, 1024)
1778 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001779
1780
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001781 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001782 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001783 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001784 process.
1785 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001786 connection = Connection(Context(TLSv1_METHOD), socket())
1787 connection.set_shutdown(RECEIVED_SHUTDOWN)
1788 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1789
1790
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05001791 if not PY3:
1792 def test_set_shutdown_long(self):
1793 """
1794 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
1795 of type :py:obj:`long` as well as :py:obj:`int`.
1796 """
1797 connection = Connection(Context(TLSv1_METHOD), socket())
1798 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
1799 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1800
1801
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001802 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001803 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001804 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
1805 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001806 with any arguments.
1807 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001808 conn = Connection(Context(TLSv1_METHOD), None)
1809 self.assertRaises(TypeError, conn.get_app_data, None)
1810 self.assertRaises(TypeError, conn.set_app_data)
1811 self.assertRaises(TypeError, conn.set_app_data, None, None)
1812
1813
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001814 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001815 """
1816 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001817 :py:obj:`Connection.set_app_data` and later retrieved with
1818 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001819 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001820 conn = Connection(Context(TLSv1_METHOD), None)
1821 app_data = object()
1822 conn.set_app_data(app_data)
1823 self.assertIdentical(conn.get_app_data(), app_data)
1824
1825
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001826 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001827 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001828 :py:obj:`Connection.makefile` is not implemented and calling that method raises
1829 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001830 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001831 conn = Connection(Context(TLSv1_METHOD), None)
1832 self.assertRaises(NotImplementedError, conn.makefile)
1833
1834
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001835 def test_get_peer_cert_chain_wrong_args(self):
1836 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001837 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001838 arguments.
1839 """
1840 conn = Connection(Context(TLSv1_METHOD), None)
1841 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
1842 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
1843 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
1844 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
1845
1846
1847 def test_get_peer_cert_chain(self):
1848 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001849 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001850 the connected server returned for the certification verification.
1851 """
1852 chain = _create_certificate_chain()
1853 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1854
1855 serverContext = Context(TLSv1_METHOD)
1856 serverContext.use_privatekey(skey)
1857 serverContext.use_certificate(scert)
1858 serverContext.add_extra_chain_cert(icert)
1859 serverContext.add_extra_chain_cert(cacert)
1860 server = Connection(serverContext, None)
1861 server.set_accept_state()
1862
1863 # Create the client
1864 clientContext = Context(TLSv1_METHOD)
1865 clientContext.set_verify(VERIFY_NONE, verify_cb)
1866 client = Connection(clientContext, None)
1867 client.set_connect_state()
1868
1869 self._interactInMemory(client, server)
1870
1871 chain = client.get_peer_cert_chain()
1872 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001873 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001874 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001875 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001876 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001877 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001878 "Authority Certificate", chain[2].get_subject().CN)
1879
1880
1881 def test_get_peer_cert_chain_none(self):
1882 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001883 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001884 certificate chain.
1885 """
1886 ctx = Context(TLSv1_METHOD)
1887 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1888 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1889 server = Connection(ctx, None)
1890 server.set_accept_state()
1891 client = Connection(Context(TLSv1_METHOD), None)
1892 client.set_connect_state()
1893 self._interactInMemory(client, server)
1894 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001895
1896
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001897 def test_get_session_wrong_args(self):
1898 """
1899 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
1900 with any arguments.
1901 """
1902 ctx = Context(TLSv1_METHOD)
1903 server = Connection(ctx, None)
1904 self.assertRaises(TypeError, server.get_session, 123)
1905 self.assertRaises(TypeError, server.get_session, "hello")
1906 self.assertRaises(TypeError, server.get_session, object())
1907
1908
1909 def test_get_session_unconnected(self):
1910 """
1911 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
1912 an object which has not been connected.
1913 """
1914 ctx = Context(TLSv1_METHOD)
1915 server = Connection(ctx, None)
1916 session = server.get_session()
1917 self.assertIdentical(None, session)
1918
1919
1920 def test_server_get_session(self):
1921 """
1922 On the server side of a connection, :py:obj:`Connection.get_session`
1923 returns a :py:class:`Session` instance representing the SSL session for
1924 that connection.
1925 """
1926 server, client = self._loopback()
1927 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001928 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001929
1930
1931 def test_client_get_session(self):
1932 """
1933 On the client side of a connection, :py:obj:`Connection.get_session`
1934 returns a :py:class:`Session` instance representing the SSL session for
1935 that connection.
1936 """
1937 server, client = self._loopback()
1938 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001939 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001940
1941
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05001942 def test_set_session_wrong_args(self):
1943 """
1944 If called with an object that is not an instance of :py:class:`Session`,
1945 or with other than one argument, :py:obj:`Connection.set_session` raises
1946 :py:obj:`TypeError`.
1947 """
1948 ctx = Context(TLSv1_METHOD)
1949 connection = Connection(ctx, None)
1950 self.assertRaises(TypeError, connection.set_session)
1951 self.assertRaises(TypeError, connection.set_session, 123)
1952 self.assertRaises(TypeError, connection.set_session, "hello")
1953 self.assertRaises(TypeError, connection.set_session, object())
1954 self.assertRaises(
1955 TypeError, connection.set_session, Session(), Session())
1956
1957
1958 def test_client_set_session(self):
1959 """
1960 :py:obj:`Connection.set_session`, when used prior to a connection being
1961 established, accepts a :py:class:`Session` instance and causes an
1962 attempt to re-use the session it represents when the SSL handshake is
1963 performed.
1964 """
1965 key = load_privatekey(FILETYPE_PEM, server_key_pem)
1966 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
1967 ctx = Context(TLSv1_METHOD)
1968 ctx.use_privatekey(key)
1969 ctx.use_certificate(cert)
1970 ctx.set_session_id("unity-test")
1971
1972 def makeServer(socket):
1973 server = Connection(ctx, socket)
1974 server.set_accept_state()
1975 return server
1976
1977 originalServer, originalClient = self._loopback(
1978 serverFactory=makeServer)
1979 originalSession = originalClient.get_session()
1980
1981 def makeClient(socket):
1982 client = self._loopbackClientFactory(socket)
1983 client.set_session(originalSession)
1984 return client
1985 resumedServer, resumedClient = self._loopback(
1986 serverFactory=makeServer,
1987 clientFactory=makeClient)
1988
1989 # This is a proxy: in general, we have no access to any unique
1990 # identifier for the session (new enough versions of OpenSSL expose a
1991 # hash which could be usable, but "new enough" is very, very new).
1992 # Instead, exploit the fact that the master key is re-used if the
1993 # session is re-used. As long as the master key for the two connections
1994 # is the same, the session was re-used!
1995 self.assertEqual(
1996 originalServer.master_key(), resumedServer.master_key())
1997
1998
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05001999 def test_set_session_wrong_method(self):
2000 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002001 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
2002 instance associated with a context using a different SSL method than the
2003 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
2004 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002005 """
2006 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2007 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2008 ctx = Context(TLSv1_METHOD)
2009 ctx.use_privatekey(key)
2010 ctx.use_certificate(cert)
2011 ctx.set_session_id("unity-test")
2012
2013 def makeServer(socket):
2014 server = Connection(ctx, socket)
2015 server.set_accept_state()
2016 return server
2017
2018 originalServer, originalClient = self._loopback(
2019 serverFactory=makeServer)
2020 originalSession = originalClient.get_session()
2021
2022 def makeClient(socket):
2023 # Intentionally use a different, incompatible method here.
2024 client = Connection(Context(SSLv3_METHOD), socket)
2025 client.set_connect_state()
2026 client.set_session(originalSession)
2027 return client
2028
2029 self.assertRaises(
2030 Error,
2031 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2032
2033
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002034 def test_wantWriteError(self):
2035 """
2036 :py:obj:`Connection` methods which generate output raise
2037 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2038 fail indicating a should-write state.
2039 """
2040 client_socket, server_socket = socket_pair()
2041 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002042 # anything. Only write a single byte at a time so we can be sure we
2043 # completely fill the buffer. Even though the socket API is allowed to
2044 # signal a short write via its return value it seems this doesn't
2045 # always happen on all platforms (FreeBSD and OS X particular) for the
2046 # very last bit of available buffer space.
2047 msg = b"x"
2048 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002049 try:
2050 client_socket.send(msg)
2051 except error as e:
2052 if e.errno == EWOULDBLOCK:
2053 break
2054 raise
2055 else:
2056 self.fail(
2057 "Failed to fill socket buffer, cannot test BIO want write")
2058
2059 ctx = Context(TLSv1_METHOD)
2060 conn = Connection(ctx, client_socket)
2061 # Client's speak first, so make it an SSL client
2062 conn.set_connect_state()
2063 self.assertRaises(WantWriteError, conn.do_handshake)
2064
2065 # XXX want_read
2066
Fedor Brunner416f4a12014-03-28 13:18:38 +01002067 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002068 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002069 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2070 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002071 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002072 ctx = Context(TLSv1_METHOD)
2073 connection = Connection(ctx, None)
2074 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002075
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002076
Fedor Brunner416f4a12014-03-28 13:18:38 +01002077 def test_get_peer_finished_before_connect(self):
2078 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002079 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2080 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002081 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002082 ctx = Context(TLSv1_METHOD)
2083 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002084 self.assertEqual(connection.get_peer_finished(), None)
2085
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002086
Fedor Brunner416f4a12014-03-28 13:18:38 +01002087 def test_get_finished(self):
2088 """
2089 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002090 message send from client, or server. Finished messages are send during
2091 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002092 """
2093
Fedor Brunner5747b932014-03-05 14:22:34 +01002094 server, client = self._loopback()
2095
2096 self.assertNotEqual(server.get_finished(), None)
2097 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002098
Jean-Paul Calderoned979f232014-03-30 11:58:00 -04002099
Fedor Brunner416f4a12014-03-28 13:18:38 +01002100 def test_get_peer_finished(self):
2101 """
2102 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002103 message received from client, or server. Finished messages are send
2104 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002105 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002106 server, client = self._loopback()
2107
2108 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002109 self.assertTrue(len(server.get_peer_finished()) > 0)
2110
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002111
Fedor Brunner416f4a12014-03-28 13:18:38 +01002112 def test_tls_finished_message_symmetry(self):
2113 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002114 The TLS Finished message send by server must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002115 received by client.
2116
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002117 The TLS Finished message send by client must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002118 received by server.
2119 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002120 server, client = self._loopback()
2121
Fedor Brunner5747b932014-03-05 14:22:34 +01002122 self.assertEqual(server.get_finished(), client.get_peer_finished())
2123 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002124
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002125
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002126 def test_get_cipher_name_before_connect(self):
2127 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002128 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2129 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002130 """
2131 ctx = Context(TLSv1_METHOD)
2132 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002133 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002134
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002135
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002136 def test_get_cipher_name(self):
2137 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002138 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2139 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002140 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002141 server, client = self._loopback()
2142 server_cipher_name, client_cipher_name = \
2143 server.get_cipher_name(), client.get_cipher_name()
2144
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002145 self.assertIsInstance(server_cipher_name, text_type)
2146 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002147
2148 self.assertEqual(server_cipher_name, client_cipher_name)
2149
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002150
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002151 def test_get_cipher_version_before_connect(self):
2152 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002153 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2154 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002155 """
2156 ctx = Context(TLSv1_METHOD)
2157 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002158 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002159
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002160
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002161 def test_get_cipher_version(self):
2162 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002163 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2164 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002165 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002166 server, client = self._loopback()
2167 server_cipher_version, client_cipher_version = \
2168 server.get_cipher_version(), client.get_cipher_version()
2169
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002170 self.assertIsInstance(server_cipher_version, text_type)
2171 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002172
2173 self.assertEqual(server_cipher_version, client_cipher_version)
2174
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002175
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002176 def test_get_cipher_bits_before_connect(self):
2177 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002178 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2179 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002180 """
2181 ctx = Context(TLSv1_METHOD)
2182 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002183 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002184
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002185
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002186 def test_get_cipher_bits(self):
2187 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002188 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2189 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002190 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002191 server, client = self._loopback()
2192 server_cipher_bits, client_cipher_bits = \
2193 server.get_cipher_bits(), client.get_cipher_bits()
2194
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002195 self.assertIsInstance(server_cipher_bits, int)
2196 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002197
2198 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002199
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002200
2201
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002202class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002203 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002204 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002205 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002206 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002207 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002208 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002209 arguments.
2210 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002211 connection = Connection(Context(TLSv1_METHOD), None)
2212 self.assertRaises(TypeError, connection.get_cipher_list, None)
2213
2214
2215 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002216 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002217 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2218 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002219 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002220 connection = Connection(Context(TLSv1_METHOD), None)
2221 ciphers = connection.get_cipher_list()
2222 self.assertTrue(isinstance(ciphers, list))
2223 for cipher in ciphers:
2224 self.assertTrue(isinstance(cipher, str))
2225
2226
2227
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002228class ConnectionSendTests(TestCase, _LoopbackMixin):
2229 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002230 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002231 """
2232 def test_wrong_args(self):
2233 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002234 When called with arguments other than string argument for its first
2235 parameter or more than two arguments, :py:obj:`Connection.send` raises
2236 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002237 """
2238 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002239 self.assertRaises(TypeError, connection.send)
2240 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002241 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002242
2243
2244 def test_short_bytes(self):
2245 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002246 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002247 and returns the number of bytes sent.
2248 """
2249 server, client = self._loopback()
2250 count = server.send(b('xy'))
2251 self.assertEquals(count, 2)
2252 self.assertEquals(client.recv(2), b('xy'))
2253
2254 try:
2255 memoryview
2256 except NameError:
2257 "cannot test sending memoryview without memoryview"
2258 else:
2259 def test_short_memoryview(self):
2260 """
2261 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002262 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002263 bytes sent.
2264 """
2265 server, client = self._loopback()
2266 count = server.send(memoryview(b('xy')))
2267 self.assertEquals(count, 2)
2268 self.assertEquals(client.recv(2), b('xy'))
2269
2270
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002271 try:
2272 buffer
2273 except NameError:
2274 "cannot test sending buffer without buffer"
2275 else:
2276 def test_short_buffer(self):
2277 """
2278 When passed a buffer containing a small number of bytes,
2279 :py:obj:`Connection.send` transmits all of them and returns the number of
2280 bytes sent.
2281 """
2282 server, client = self._loopback()
2283 count = server.send(buffer(b('xy')))
2284 self.assertEquals(count, 2)
2285 self.assertEquals(client.recv(2), b('xy'))
2286
2287
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002288
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002289class ConnectionSendallTests(TestCase, _LoopbackMixin):
2290 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002291 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002292 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002293 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002294 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002295 When called with arguments other than a string argument for its first
2296 parameter or with more than two arguments, :py:obj:`Connection.sendall`
2297 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002298 """
2299 connection = Connection(Context(TLSv1_METHOD), None)
2300 self.assertRaises(TypeError, connection.sendall)
2301 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002302 self.assertRaises(
2303 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002304
2305
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002306 def test_short(self):
2307 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002308 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002309 it.
2310 """
2311 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04002312 server.sendall(b('x'))
2313 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002314
2315
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002316 try:
2317 memoryview
2318 except NameError:
2319 "cannot test sending memoryview without memoryview"
2320 else:
2321 def test_short_memoryview(self):
2322 """
2323 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002324 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002325 """
2326 server, client = self._loopback()
2327 server.sendall(memoryview(b('x')))
2328 self.assertEquals(client.recv(1), b('x'))
2329
2330
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002331 try:
2332 buffer
2333 except NameError:
2334 "cannot test sending buffers without buffers"
2335 else:
2336 def test_short_buffers(self):
2337 """
2338 When passed a buffer containing a small number of bytes,
2339 :py:obj:`Connection.sendall` transmits all of them.
2340 """
2341 server, client = self._loopback()
2342 server.sendall(buffer(b('x')))
2343 self.assertEquals(client.recv(1), b('x'))
2344
2345
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002346 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002347 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002348 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002349 it even if this requires multiple calls of an underlying write function.
2350 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002351 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04002352 # Should be enough, underlying SSL_write should only do 16k at a time.
2353 # On Windows, after 32k of bytes the write will block (forever - because
2354 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04002355 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002356 server.sendall(message)
2357 accum = []
2358 received = 0
2359 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04002360 data = client.recv(1024)
2361 accum.append(data)
2362 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04002363 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002364
2365
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002366 def test_closed(self):
2367 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002368 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002369 write error from the low level write call.
2370 """
2371 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04002372 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002373 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02002374 if platform == "win32":
2375 self.assertEqual(exc.args[0], ESHUTDOWN)
2376 else:
2377 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002378
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002379
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002380
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002381class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
2382 """
2383 Tests for SSL renegotiation APIs.
2384 """
2385 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002386 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002387 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002388 arguments.
2389 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002390 connection = Connection(Context(TLSv1_METHOD), None)
2391 self.assertRaises(TypeError, connection.renegotiate, None)
2392
2393
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002394 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002395 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002396 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002397 any arguments.
2398 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002399 connection = Connection(Context(TLSv1_METHOD), None)
2400 self.assertRaises(TypeError, connection.total_renegotiations, None)
2401
2402
2403 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002404 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002405 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002406 renegotiations have happened.
2407 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002408 connection = Connection(Context(TLSv1_METHOD), None)
2409 self.assertEquals(connection.total_renegotiations(), 0)
2410
2411
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002412# def test_renegotiate(self):
2413# """
2414# """
2415# server, client = self._loopback()
2416
2417# server.send("hello world")
2418# self.assertEquals(client.recv(len("hello world")), "hello world")
2419
2420# self.assertEquals(server.total_renegotiations(), 0)
2421# self.assertTrue(server.renegotiate())
2422
2423# server.setblocking(False)
2424# client.setblocking(False)
2425# while server.renegotiate_pending():
2426# client.do_handshake()
2427# server.do_handshake()
2428
2429# self.assertEquals(server.total_renegotiations(), 1)
2430
2431
2432
2433
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002434class ErrorTests(TestCase):
2435 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002436 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002437 """
2438 def test_type(self):
2439 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002440 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002441 """
2442 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05002443 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05002444
2445
2446
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002447class ConstantsTests(TestCase):
2448 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002449 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002450
2451 These are values defined by OpenSSL intended only to be used as flags to
2452 OpenSSL APIs. The only assertions it seems can be made about them is
2453 their values.
2454 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002455 # unittest.TestCase has no skip mechanism
2456 if OP_NO_QUERY_MTU is not None:
2457 def test_op_no_query_mtu(self):
2458 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002459 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002460 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002461 """
2462 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
2463 else:
2464 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002465
2466
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002467 if OP_COOKIE_EXCHANGE is not None:
2468 def test_op_cookie_exchange(self):
2469 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002470 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002471 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002472 """
2473 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
2474 else:
2475 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002476
2477
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002478 if OP_NO_TICKET is not None:
2479 def test_op_no_ticket(self):
2480 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002481 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002482 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002483 """
2484 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04002485 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002486 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05002487
2488
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002489 if OP_NO_COMPRESSION is not None:
2490 def test_op_no_compression(self):
2491 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002492 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
2493 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002494 """
2495 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
2496 else:
2497 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
2498
2499
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002500 def test_sess_cache_off(self):
2501 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002502 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
2503 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002504 """
2505 self.assertEqual(0x0, SESS_CACHE_OFF)
2506
2507
2508 def test_sess_cache_client(self):
2509 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002510 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
2511 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002512 """
2513 self.assertEqual(0x1, SESS_CACHE_CLIENT)
2514
2515
2516 def test_sess_cache_server(self):
2517 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002518 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
2519 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002520 """
2521 self.assertEqual(0x2, SESS_CACHE_SERVER)
2522
2523
2524 def test_sess_cache_both(self):
2525 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002526 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
2527 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002528 """
2529 self.assertEqual(0x3, SESS_CACHE_BOTH)
2530
2531
2532 def test_sess_cache_no_auto_clear(self):
2533 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002534 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
2535 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
2536 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002537 """
2538 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
2539
2540
2541 def test_sess_cache_no_internal_lookup(self):
2542 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002543 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
2544 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
2545 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002546 """
2547 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
2548
2549
2550 def test_sess_cache_no_internal_store(self):
2551 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002552 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
2553 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
2554 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002555 """
2556 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
2557
2558
2559 def test_sess_cache_no_internal(self):
2560 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002561 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
2562 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
2563 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002564 """
2565 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
2566
2567
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04002568
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002569class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05002570 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002571 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05002572 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002573 def _server(self, sock):
2574 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002575 Create a new server-side SSL :py:obj:`Connection` object wrapped around
2576 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002577 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002578 # Create the server side Connection. This is mostly setup boilerplate
2579 # - use TLSv1, use a particular certificate, etc.
2580 server_ctx = Context(TLSv1_METHOD)
2581 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2582 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2583 server_store = server_ctx.get_cert_store()
2584 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2585 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2586 server_ctx.check_privatekey()
2587 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002588 # Here the Connection is actually created. If None is passed as the 2nd
2589 # parameter, it indicates a memory BIO should be created.
2590 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002591 server_conn.set_accept_state()
2592 return server_conn
2593
2594
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002595 def _client(self, sock):
2596 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002597 Create a new client-side SSL :py:obj:`Connection` object wrapped around
2598 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002599 """
2600 # Now create the client side Connection. Similar boilerplate to the
2601 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002602 client_ctx = Context(TLSv1_METHOD)
2603 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2604 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2605 client_store = client_ctx.get_cert_store()
2606 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
2607 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
2608 client_ctx.check_privatekey()
2609 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002610 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002611 client_conn.set_connect_state()
2612 return client_conn
2613
2614
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002615 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002616 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002617 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002618 reading from the output of each and writing those bytes to the input of
2619 the other and in this way establish a connection and exchange
2620 application-level bytes with each other.
2621 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002622 server_conn = self._server(None)
2623 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002624
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002625 # There should be no key or nonces yet.
2626 self.assertIdentical(server_conn.master_key(), None)
2627 self.assertIdentical(server_conn.client_random(), None)
2628 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002629
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002630 # First, the handshake needs to happen. We'll deliver bytes back and
2631 # forth between the client and server until neither of them feels like
2632 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002633 self.assertIdentical(
2634 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002635
2636 # Now that the handshake is done, there should be a key and nonces.
2637 self.assertNotIdentical(server_conn.master_key(), None)
2638 self.assertNotIdentical(server_conn.client_random(), None)
2639 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04002640 self.assertEquals(server_conn.client_random(), client_conn.client_random())
2641 self.assertEquals(server_conn.server_random(), client_conn.server_random())
2642 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
2643 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002644
2645 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002646 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05002647
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002648 server_conn.write(important_message)
2649 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002650 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002651 (client_conn, important_message))
2652
2653 client_conn.write(important_message[::-1])
2654 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002655 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002656 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05002657
2658
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002659 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05002660 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002661 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002662
2663 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09002664 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002665 this test fails, there must be a problem outside the memory BIO
2666 code, as no memory BIO is involved here). Even though this isn't a
2667 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05002668 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04002669 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05002670
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002671 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05002672 client_conn.send(important_message)
2673 msg = server_conn.recv(1024)
2674 self.assertEqual(msg, important_message)
2675
2676 # Again in the other direction, just for fun.
2677 important_message = important_message[::-1]
2678 server_conn.send(important_message)
2679 msg = client_conn.recv(1024)
2680 self.assertEqual(msg, important_message)
2681
2682
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04002683 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05002684 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002685 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
2686 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05002687 """
2688 context = Context(SSLv3_METHOD)
2689 client = socket()
2690 clientSSL = Connection(context, client)
2691 self.assertRaises( TypeError, clientSSL.bio_read, 100)
2692 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04002693 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002694
2695
2696 def test_outgoingOverflow(self):
2697 """
2698 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002699 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002700 returned and that many bytes from the beginning of the input can be
2701 read from the other end of the connection.
2702 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002703 server = self._server(None)
2704 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002705
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002706 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002707
2708 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002709 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002710 # Sanity check. We're trying to test what happens when the entire
2711 # input can't be sent. If the entire input was sent, this test is
2712 # meaningless.
2713 self.assertTrue(sent < size)
2714
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002715 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002716 self.assertIdentical(receiver, server)
2717
2718 # We can rely on all of these bytes being received at once because
2719 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
2720 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002721
2722
2723 def test_shutdown(self):
2724 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002725 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
2726 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002727 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002728 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002729 server.bio_shutdown()
2730 e = self.assertRaises(Error, server.recv, 1024)
2731 # We don't want WantReadError or ZeroReturnError or anything - it's a
2732 # handshake failure.
2733 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002734
2735
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002736 def test_unexpectedEndOfFile(self):
2737 """
2738 If the connection is lost before an orderly SSL shutdown occurs,
2739 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
2740 "Unexpected EOF".
2741 """
2742 server_conn, client_conn = self._loopback()
2743 client_conn.sock_shutdown(SHUT_RDWR)
2744 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
2745 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
2746
2747
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002748 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002749 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002750 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 -04002751
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002752 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002753 before the client and server are connected to each other. This
2754 function should specify a list of CAs for the server to send to the
2755 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09002756 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002757 times.
2758 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002759 server = self._server(None)
2760 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002761 self.assertEqual(client.get_client_ca_list(), [])
2762 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002763 ctx = server.get_context()
2764 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002765 self.assertEqual(client.get_client_ca_list(), [])
2766 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002767 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002768 self.assertEqual(client.get_client_ca_list(), expected)
2769 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002770
2771
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002772 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002773 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002774 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002775 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002776 """
2777 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002778 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
2779 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
2780 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002781
2782
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002783 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002784 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002785 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002786 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09002787 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002788 after the connection is set up.
2789 """
2790 def no_ca(ctx):
2791 ctx.set_client_ca_list([])
2792 return []
2793 self._check_client_ca_list(no_ca)
2794
2795
2796 def test_set_one_ca_list(self):
2797 """
2798 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002799 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002800 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002801 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002802 X509Name after the connection is set up.
2803 """
2804 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2805 cadesc = cacert.get_subject()
2806 def single_ca(ctx):
2807 ctx.set_client_ca_list([cadesc])
2808 return [cadesc]
2809 self._check_client_ca_list(single_ca)
2810
2811
2812 def test_set_multiple_ca_list(self):
2813 """
2814 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002815 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002816 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002817 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002818 X509Names after the connection is set up.
2819 """
2820 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2821 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2822
2823 sedesc = secert.get_subject()
2824 cldesc = clcert.get_subject()
2825
2826 def multiple_ca(ctx):
2827 L = [sedesc, cldesc]
2828 ctx.set_client_ca_list(L)
2829 return L
2830 self._check_client_ca_list(multiple_ca)
2831
2832
2833 def test_reset_ca_list(self):
2834 """
2835 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09002836 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002837 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002838 """
2839 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2840 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2841 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2842
2843 cadesc = cacert.get_subject()
2844 sedesc = secert.get_subject()
2845 cldesc = clcert.get_subject()
2846
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002847 def changed_ca(ctx):
2848 ctx.set_client_ca_list([sedesc, cldesc])
2849 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002850 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002851 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002852
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002853
2854 def test_mutated_ca_list(self):
2855 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002856 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002857 afterwards, this does not affect the list of CA names sent to the
2858 client.
2859 """
2860 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2861 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2862
2863 cadesc = cacert.get_subject()
2864 sedesc = secert.get_subject()
2865
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002866 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002867 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002868 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002869 L.append(sedesc)
2870 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002871 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002872
2873
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002874 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002875 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002876 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002877 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002878 """
2879 ctx = Context(TLSv1_METHOD)
2880 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002881 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002882 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002883 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002884
2885
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002886 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002887 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002888 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09002889 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002890 """
2891 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2892 cadesc = cacert.get_subject()
2893 def single_ca(ctx):
2894 ctx.add_client_ca(cacert)
2895 return [cadesc]
2896 self._check_client_ca_list(single_ca)
2897
2898
2899 def test_multiple_add_client_ca(self):
2900 """
2901 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09002902 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002903 """
2904 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2905 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2906
2907 cadesc = cacert.get_subject()
2908 sedesc = secert.get_subject()
2909
2910 def multiple_ca(ctx):
2911 ctx.add_client_ca(cacert)
2912 ctx.add_client_ca(secert)
2913 return [cadesc, sedesc]
2914 self._check_client_ca_list(multiple_ca)
2915
2916
2917 def test_set_and_add_client_ca(self):
2918 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002919 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
2920 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002921 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002922 """
2923 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2924 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2925 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2926
2927 cadesc = cacert.get_subject()
2928 sedesc = secert.get_subject()
2929 cldesc = clcert.get_subject()
2930
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002931 def mixed_set_add_ca(ctx):
2932 ctx.set_client_ca_list([cadesc, sedesc])
2933 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002934 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002935 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002936
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002937
2938 def test_set_after_add_client_ca(self):
2939 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002940 A call to :py:obj:`Context.set_client_ca_list` after a call to
2941 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002942 call with the names specified by the latter cal.
2943 """
2944 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2945 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2946 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2947
2948 cadesc = cacert.get_subject()
2949 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002950
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002951 def set_replaces_add_ca(ctx):
2952 ctx.add_client_ca(clcert)
2953 ctx.set_client_ca_list([cadesc])
2954 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002955 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002956 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002957
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002958
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002959
2960class ConnectionBIOTests(TestCase):
2961 """
2962 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
2963 """
2964 def test_wantReadError(self):
2965 """
2966 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
2967 if there are no bytes available to be read from the BIO.
2968 """
2969 ctx = Context(TLSv1_METHOD)
2970 conn = Connection(ctx, None)
2971 self.assertRaises(WantReadError, conn.bio_read, 1024)
2972
2973
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002974 def test_buffer_size(self):
2975 """
2976 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
2977 number of bytes to read and return.
2978 """
2979 ctx = Context(TLSv1_METHOD)
2980 conn = Connection(ctx, None)
2981 conn.set_connect_state()
2982 try:
2983 conn.do_handshake()
2984 except WantReadError:
2985 pass
2986 data = conn.bio_read(2)
2987 self.assertEqual(2, len(data))
2988
2989
2990 if not PY3:
2991 def test_buffer_size_long(self):
2992 """
2993 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
2994 :py:obj:`long` as well as :py:obj:`int`.
2995 """
2996 ctx = Context(TLSv1_METHOD)
2997 conn = Connection(ctx, None)
2998 conn.set_connect_state()
2999 try:
3000 conn.do_handshake()
3001 except WantReadError:
3002 pass
3003 data = conn.bio_read(long(2))
3004 self.assertEqual(2, len(data))
3005
3006
3007
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003008
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003009class InfoConstantTests(TestCase):
3010 """
3011 Tests for assorted constants exposed for use in info callbacks.
3012 """
3013 def test_integers(self):
3014 """
3015 All of the info constants are integers.
3016
3017 This is a very weak test. It would be nice to have one that actually
3018 verifies that as certain info events happen, the value passed to the
3019 info callback matches up with the constant exposed by OpenSSL.SSL.
3020 """
3021 for const in [
3022 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3023 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3024 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3025 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3026 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
3027 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
3028
3029 self.assertTrue(isinstance(const, int))
3030
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003031
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003032if __name__ == '__main__':
3033 main()