blob: f098327c7f6244e1646f51085fd46a2aa44561cc [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 Calderonec4cb6582011-05-26 18:47:00 -040010from sys import platform, version_info
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 Calderone7f0ded42014-03-30 10:34:17 -040017from six import PY3, 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 Calderoneb41d1f42014-04-17 16:02:04 -040025from OpenSSL.SSL import _lib
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040026from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
27from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040028from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040029from OpenSSL.SSL import (
30 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
31 TLSv1_1_METHOD, TLSv1_2_METHOD)
32from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040033from OpenSSL.SSL import (
34 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040035
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040036from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050037 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
38 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
39 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
40
41from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070042 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050043from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070044 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040045
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050046from OpenSSL.test.util import TestCase, b
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040047from OpenSSL.test.test_crypto import (
48 cleartextCertificatePEM, cleartextPrivateKeyPEM)
49from OpenSSL.test.test_crypto import (
50 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
51 root_cert_pem)
52
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050053try:
54 from OpenSSL.SSL import OP_NO_QUERY_MTU
55except ImportError:
56 OP_NO_QUERY_MTU = None
57try:
58 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
59except ImportError:
60 OP_COOKIE_EXCHANGE = None
61try:
62 from OpenSSL.SSL import OP_NO_TICKET
63except ImportError:
64 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040065
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040066try:
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -040067 from OpenSSL.SSL import OP_NO_COMPRESSION
68except ImportError:
69 OP_NO_COMPRESSION = None
70
71try:
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040072 from OpenSSL.SSL import MODE_RELEASE_BUFFERS
73except ImportError:
74 MODE_RELEASE_BUFFERS = None
75
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040076try:
77 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
78except ImportError:
79 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
80
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040081from OpenSSL.SSL import (
82 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
83 SSL_ST_OK, SSL_ST_RENEGOTIATE,
84 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
85 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
86 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
87 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040088
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040089# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
90# to use)
91dhparam = """\
92-----BEGIN DH PARAMETERS-----
93MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
94-----END DH PARAMETERS-----
95"""
96
97
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040098def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040099 return ok
100
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400101
Rick Deanb1ccd562009-07-09 23:52:39 -0500102def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400103 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400104 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400105 """
106 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500107 port = socket()
108 port.bind(('', 0))
109 port.listen(1)
110 client = socket()
111 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400112 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400113 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500114 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500115
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400116 # Let's pass some unencrypted data to make sure our socket connection is
117 # fine. Just one byte, so we don't have to worry about buffers getting
118 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400119 server.send(b("x"))
120 assert client.recv(1024) == b("x")
121 client.send(b("y"))
122 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500123
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400124 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400125 server.setblocking(False)
126 client.setblocking(False)
127
Rick Deanb1ccd562009-07-09 23:52:39 -0500128 return (server, client)
129
130
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400131
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400132def handshake(client, server):
133 conns = [client, server]
134 while conns:
135 for conn in conns:
136 try:
137 conn.do_handshake()
138 except WantReadError:
139 pass
140 else:
141 conns.remove(conn)
142
143
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400144def _create_certificate_chain():
145 """
146 Construct and return a chain of certificates.
147
148 1. A new self-signed certificate authority certificate (cacert)
149 2. A new intermediate certificate signed by cacert (icert)
150 3. A new server certificate signed by icert (scert)
151 """
152 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
153
154 # Step 1
155 cakey = PKey()
156 cakey.generate_key(TYPE_RSA, 512)
157 cacert = X509()
158 cacert.get_subject().commonName = "Authority Certificate"
159 cacert.set_issuer(cacert.get_subject())
160 cacert.set_pubkey(cakey)
161 cacert.set_notBefore(b("20000101000000Z"))
162 cacert.set_notAfter(b("20200101000000Z"))
163 cacert.add_extensions([caext])
164 cacert.set_serial_number(0)
165 cacert.sign(cakey, "sha1")
166
167 # Step 2
168 ikey = PKey()
169 ikey.generate_key(TYPE_RSA, 512)
170 icert = X509()
171 icert.get_subject().commonName = "Intermediate Certificate"
172 icert.set_issuer(cacert.get_subject())
173 icert.set_pubkey(ikey)
174 icert.set_notBefore(b("20000101000000Z"))
175 icert.set_notAfter(b("20200101000000Z"))
176 icert.add_extensions([caext])
177 icert.set_serial_number(0)
178 icert.sign(cakey, "sha1")
179
180 # Step 3
181 skey = PKey()
182 skey.generate_key(TYPE_RSA, 512)
183 scert = X509()
184 scert.get_subject().commonName = "Server Certificate"
185 scert.set_issuer(icert.get_subject())
186 scert.set_pubkey(skey)
187 scert.set_notBefore(b("20000101000000Z"))
188 scert.set_notAfter(b("20200101000000Z"))
189 scert.add_extensions([
190 X509Extension(b('basicConstraints'), True, b('CA:false'))])
191 scert.set_serial_number(0)
192 scert.sign(ikey, "sha1")
193
194 return [(cakey, cacert), (ikey, icert), (skey, scert)]
195
196
197
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400198class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400199 """
200 Helper mixin which defines methods for creating a connected socket pair and
201 for forcing two connected SSL sockets to talk to each other via memory BIOs.
202 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500203 def _loopbackClientFactory(self, socket):
204 client = Connection(Context(TLSv1_METHOD), socket)
205 client.set_connect_state()
206 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400207
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500208
209 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400210 ctx = Context(TLSv1_METHOD)
211 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
212 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500213 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400214 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500215 return server
216
217
218 def _loopback(self, serverFactory=None, clientFactory=None):
219 if serverFactory is None:
220 serverFactory = self._loopbackServerFactory
221 if clientFactory is None:
222 clientFactory = self._loopbackClientFactory
223
224 (server, client) = socket_pair()
225 server = serverFactory(server)
226 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400227
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400228 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400229
230 server.setblocking(True)
231 client.setblocking(True)
232 return server, client
233
234
235 def _interactInMemory(self, client_conn, server_conn):
236 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900237 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400238 objects. Copy bytes back and forth between their send/receive buffers
239 for as long as there is anything to copy. When there is nothing more
Jonathan Ballet648875f2011-07-16 14:14:58 +0900240 to copy, return :py:obj:`None`. If one of them actually manages to deliver
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400241 some application bytes, return a two-tuple of the connection from which
242 the bytes were read and the bytes themselves.
243 """
244 wrote = True
245 while wrote:
246 # Loop until neither side has anything to say
247 wrote = False
248
249 # Copy stuff from each side's send buffer to the other side's
250 # receive buffer.
251 for (read, write) in [(client_conn, server_conn),
252 (server_conn, client_conn)]:
253
254 # Give the side a chance to generate some more bytes, or
255 # succeed.
256 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400257 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400258 except WantReadError:
259 # It didn't succeed, so we'll hope it generated some
260 # output.
261 pass
262 else:
263 # It did succeed, so we'll stop now and let the caller deal
264 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400265 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400266
267 while True:
268 # Keep copying as long as there's more stuff there.
269 try:
270 dirty = read.bio_read(4096)
271 except WantReadError:
272 # Okay, nothing more waiting to be sent. Stop
273 # processing this send buffer.
274 break
275 else:
276 # Keep track of the fact that someone generated some
277 # output.
278 wrote = True
279 write.bio_write(dirty)
280
281
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400282 def _handshakeInMemory(self, client_conn, server_conn):
Jean-Paul Calderoneb2b40782014-05-06 08:47:40 -0400283 """
284 Perform the TLS handshake between two :py:class:`Connection` instances
285 connected to each other via memory BIOs.
286 """
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400287 client_conn.set_connect_state()
288 server_conn.set_accept_state()
289
290 for conn in [client_conn, server_conn]:
291 try:
292 conn.do_handshake()
293 except WantReadError:
294 pass
295
296 self._interactInMemory(client_conn, server_conn)
297
298
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400299
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400300class VersionTests(TestCase):
301 """
302 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900303 :py:obj:`OpenSSL.SSL.SSLeay_version` and
304 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400305 """
306 def test_OPENSSL_VERSION_NUMBER(self):
307 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900308 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400309 byte and the patch, fix, minor, and major versions in the
310 nibbles above that.
311 """
312 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
313
314
315 def test_SSLeay_version(self):
316 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900317 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400318 one of a number of version strings based on that indicator.
319 """
320 versions = {}
321 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
322 SSLEAY_PLATFORM, SSLEAY_DIR]:
323 version = SSLeay_version(t)
324 versions[version] = t
325 self.assertTrue(isinstance(version, bytes))
326 self.assertEqual(len(versions), 5)
327
328
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400329
330class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400331 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900332 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400333 """
334 def test_method(self):
335 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900336 :py:obj:`Context` can be instantiated with one of :py:obj:`SSLv2_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400337 :py:obj:`SSLv3_METHOD`, :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
338 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400339 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400340 methods = [
341 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
342 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400343 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400344
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400345
346 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
347 for meth in maybe:
348 try:
349 Context(meth)
350 except (Error, ValueError):
351 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
352 # don't. Difficult to say in advance.
353 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400354
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400355 self.assertRaises(TypeError, Context, "")
356 self.assertRaises(ValueError, Context, 10)
357
358
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500359 if not PY3:
360 def test_method_long(self):
361 """
362 On Python 2 :py:class:`Context` accepts values of type
363 :py:obj:`long` as well as :py:obj:`int`.
364 """
365 Context(long(TLSv1_METHOD))
366
367
368
Rick Deane15b1472009-07-09 15:53:42 -0500369 def test_type(self):
370 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900371 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400372 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500373 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400374 self.assertIdentical(Context, ContextType)
375 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500376
377
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400378 def test_use_privatekey(self):
379 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900380 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400381 """
382 key = PKey()
383 key.generate_key(TYPE_RSA, 128)
384 ctx = Context(TLSv1_METHOD)
385 ctx.use_privatekey(key)
386 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400387
388
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800389 def test_use_privatekey_file_missing(self):
390 """
391 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error`
392 when passed the name of a file which does not exist.
393 """
394 ctx = Context(TLSv1_METHOD)
395 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
396
397
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500398 if not PY3:
399 def test_use_privatekey_file_long(self):
400 """
401 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
402 filetype of type :py:obj:`long` as well as :py:obj:`int`.
403 """
404 pemfile = self.mktemp()
405
406 key = PKey()
407 key.generate_key(TYPE_RSA, 128)
408
409 with open(pemfile, "wt") as pem:
410 pem.write(
411 dump_privatekey(FILETYPE_PEM, key).decode("ascii"))
412
413 ctx = Context(TLSv1_METHOD)
414 ctx.use_privatekey_file(pemfile, long(FILETYPE_PEM))
415
416
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800417 def test_use_certificate_wrong_args(self):
418 """
419 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
420 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as an
421 argument.
422 """
423 ctx = Context(TLSv1_METHOD)
424 self.assertRaises(TypeError, ctx.use_certificate)
425 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
426 self.assertRaises(TypeError, ctx.use_certificate, X509(), "hello, world")
427
428
429 def test_use_certificate_uninitialized(self):
430 """
431 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
432 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
433 initialized (ie, which does not actually have any certificate data).
434 """
435 ctx = Context(TLSv1_METHOD)
436 self.assertRaises(Error, ctx.use_certificate, X509())
437
438
439 def test_use_certificate(self):
440 """
441 :py:obj:`Context.use_certificate` sets the certificate which will be
442 used to identify connections created using the context.
443 """
444 # TODO
445 # Hard to assert anything. But we could set a privatekey then ask
446 # OpenSSL if the cert and key agree using check_privatekey. Then as
447 # long as check_privatekey works right we're good...
448 ctx = Context(TLSv1_METHOD)
449 ctx.use_certificate(load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
450
451
452 def test_use_certificate_file_wrong_args(self):
453 """
454 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
455 called with zero arguments or more than two arguments, or if the first
456 argument is not a byte string or the second argumnent is not an integer.
457 """
458 ctx = Context(TLSv1_METHOD)
459 self.assertRaises(TypeError, ctx.use_certificate_file)
460 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile", object())
461 self.assertRaises(
462 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM, object())
463 self.assertRaises(
464 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
465 self.assertRaises(
466 TypeError, ctx.use_certificate_file, b"somefile", object())
467
468
469 def test_use_certificate_file_missing(self):
470 """
471 :py:obj:`Context.use_certificate_file` raises
472 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does not
473 exist.
474 """
475 ctx = Context(TLSv1_METHOD)
476 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
477
478
479 def test_use_certificate_file(self):
480 """
481 :py:obj:`Context.use_certificate` sets the certificate which will be
482 used to identify connections created using the context.
483 """
484 # TODO
485 # Hard to assert anything. But we could set a privatekey then ask
486 # OpenSSL if the cert and key agree using check_privatekey. Then as
487 # long as check_privatekey works right we're good...
488 pem_filename = self.mktemp()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500489 with open(pem_filename, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800490 pem_file.write(cleartextCertificatePEM)
491
492 ctx = Context(TLSv1_METHOD)
493 ctx.use_certificate_file(pem_filename)
494
495
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500496 if not PY3:
497 def test_use_certificate_file_long(self):
498 """
499 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
500 filetype of type :py:obj:`long` as well as :py:obj:`int`.
501 """
502 pem_filename = self.mktemp()
503 with open(pem_filename, "wb") as pem_file:
504 pem_file.write(cleartextCertificatePEM)
505
506 ctx = Context(TLSv1_METHOD)
507 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
508
509
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500510 def test_check_privatekey_valid(self):
511 """
512 :py:obj:`Context.check_privatekey` returns :py:obj:`None` if the
513 :py:obj:`Context` instance has been configured to use a matched key and
514 certificate pair.
515 """
516 key = load_privatekey(FILETYPE_PEM, client_key_pem)
517 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
518 context = Context(TLSv1_METHOD)
519 context.use_privatekey(key)
520 context.use_certificate(cert)
521 self.assertIs(None, context.check_privatekey())
522
523
524 def test_check_privatekey_invalid(self):
525 """
526 :py:obj:`Context.check_privatekey` raises :py:obj:`Error` if the
527 :py:obj:`Context` instance has been configured to use a key and
528 certificate pair which don't relate to each other.
529 """
530 key = load_privatekey(FILETYPE_PEM, client_key_pem)
531 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
532 context = Context(TLSv1_METHOD)
533 context.use_privatekey(key)
534 context.use_certificate(cert)
535 self.assertRaises(Error, context.check_privatekey)
536
537
538 def test_check_privatekey_wrong_args(self):
539 """
540 :py:obj:`Context.check_privatekey` raises :py:obj:`TypeError` if called
541 with other than no arguments.
542 """
543 context = Context(TLSv1_METHOD)
544 self.assertRaises(TypeError, context.check_privatekey, object())
545
546
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400547 def test_set_app_data_wrong_args(self):
548 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900549 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called with other than
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400550 one argument.
551 """
552 context = Context(TLSv1_METHOD)
553 self.assertRaises(TypeError, context.set_app_data)
554 self.assertRaises(TypeError, context.set_app_data, None, None)
555
556
557 def test_get_app_data_wrong_args(self):
558 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900559 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400560 arguments.
561 """
562 context = Context(TLSv1_METHOD)
563 self.assertRaises(TypeError, context.get_app_data, None)
564
565
566 def test_app_data(self):
567 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900568 :py:obj:`Context.set_app_data` stores an object for later retrieval using
569 :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400570 """
571 app_data = object()
572 context = Context(TLSv1_METHOD)
573 context.set_app_data(app_data)
574 self.assertIdentical(context.get_app_data(), app_data)
575
576
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400577 def test_set_options_wrong_args(self):
578 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900579 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with the wrong
580 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400581 """
582 context = Context(TLSv1_METHOD)
583 self.assertRaises(TypeError, context.set_options)
584 self.assertRaises(TypeError, context.set_options, None)
585 self.assertRaises(TypeError, context.set_options, 1, None)
586
587
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500588 def test_set_options(self):
589 """
590 :py:obj:`Context.set_options` returns the new options value.
591 """
592 context = Context(TLSv1_METHOD)
593 options = context.set_options(OP_NO_SSLv2)
594 self.assertTrue(OP_NO_SSLv2 & options)
595
596
597 if not PY3:
598 def test_set_options_long(self):
599 """
600 On Python 2 :py:obj:`Context.set_options` accepts values of type
601 :py:obj:`long` as well as :py:obj:`int`.
602 """
603 context = Context(TLSv1_METHOD)
604 options = context.set_options(long(OP_NO_SSLv2))
605 self.assertTrue(OP_NO_SSLv2 & options)
606
607
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300608 def test_set_mode_wrong_args(self):
609 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400610 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with the wrong
611 number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300612 """
613 context = Context(TLSv1_METHOD)
614 self.assertRaises(TypeError, context.set_mode)
615 self.assertRaises(TypeError, context.set_mode, None)
616 self.assertRaises(TypeError, context.set_mode, 1, None)
617
618
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400619 if MODE_RELEASE_BUFFERS is not None:
620 def test_set_mode(self):
621 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400622 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the newly
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400623 set mode.
624 """
625 context = Context(TLSv1_METHOD)
626 self.assertTrue(
627 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500628
629 if not PY3:
630 def test_set_mode_long(self):
631 """
632 On Python 2 :py:obj:`Context.set_mode` accepts values of type
633 :py:obj:`long` as well as :py:obj:`int`.
634 """
635 context = Context(TLSv1_METHOD)
636 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
637 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400638 else:
639 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
640
641
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400642 def test_set_timeout_wrong_args(self):
643 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900644 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with the wrong
645 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400646 """
647 context = Context(TLSv1_METHOD)
648 self.assertRaises(TypeError, context.set_timeout)
649 self.assertRaises(TypeError, context.set_timeout, None)
650 self.assertRaises(TypeError, context.set_timeout, 1, None)
651
652
653 def test_get_timeout_wrong_args(self):
654 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900655 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400656 """
657 context = Context(TLSv1_METHOD)
658 self.assertRaises(TypeError, context.get_timeout, None)
659
660
661 def test_timeout(self):
662 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900663 :py:obj:`Context.set_timeout` sets the session timeout for all connections
664 created using the context object. :py:obj:`Context.get_timeout` retrieves this
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400665 value.
666 """
667 context = Context(TLSv1_METHOD)
668 context.set_timeout(1234)
669 self.assertEquals(context.get_timeout(), 1234)
670
671
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500672 if not PY3:
673 def test_timeout_long(self):
674 """
675 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
676 `long` as well as int.
677 """
678 context = Context(TLSv1_METHOD)
679 context.set_timeout(long(1234))
680 self.assertEquals(context.get_timeout(), 1234)
681
682
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400683 def test_set_verify_depth_wrong_args(self):
684 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900685 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called with the wrong
686 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400687 """
688 context = Context(TLSv1_METHOD)
689 self.assertRaises(TypeError, context.set_verify_depth)
690 self.assertRaises(TypeError, context.set_verify_depth, None)
691 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
692
693
694 def test_get_verify_depth_wrong_args(self):
695 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900696 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400697 """
698 context = Context(TLSv1_METHOD)
699 self.assertRaises(TypeError, context.get_verify_depth, None)
700
701
702 def test_verify_depth(self):
703 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900704 :py:obj:`Context.set_verify_depth` sets the number of certificates in a chain
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400705 to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900706 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400707 """
708 context = Context(TLSv1_METHOD)
709 context.set_verify_depth(11)
710 self.assertEquals(context.get_verify_depth(), 11)
711
712
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500713 if not PY3:
714 def test_verify_depth_long(self):
715 """
716 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
717 type `long` as well as int.
718 """
719 context = Context(TLSv1_METHOD)
720 context.set_verify_depth(long(11))
721 self.assertEquals(context.get_verify_depth(), 11)
722
723
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400724 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400725 """
726 Write a new private key out to a new file, encrypted using the given
727 passphrase. Return the path to the new file.
728 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400729 key = PKey()
730 key.generate_key(TYPE_RSA, 128)
731 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400732 fObj = open(pemFile, 'w')
733 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
734 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400735 fObj.close()
736 return pemFile
737
738
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400739 def test_set_passwd_cb_wrong_args(self):
740 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900741 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called with the
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400742 wrong arguments or with a non-callable first argument.
743 """
744 context = Context(TLSv1_METHOD)
745 self.assertRaises(TypeError, context.set_passwd_cb)
746 self.assertRaises(TypeError, context.set_passwd_cb, None)
747 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
748
749
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400750 def test_set_passwd_cb(self):
751 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900752 :py:obj:`Context.set_passwd_cb` accepts a callable which will be invoked when
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400753 a private key is loaded from an encrypted PEM.
754 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400755 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400756 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400757 calledWith = []
758 def passphraseCallback(maxlen, verify, extra):
759 calledWith.append((maxlen, verify, extra))
760 return passphrase
761 context = Context(TLSv1_METHOD)
762 context.set_passwd_cb(passphraseCallback)
763 context.use_privatekey_file(pemFile)
764 self.assertTrue(len(calledWith), 1)
765 self.assertTrue(isinstance(calledWith[0][0], int))
766 self.assertTrue(isinstance(calledWith[0][1], int))
767 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400768
769
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400770 def test_passwd_callback_exception(self):
771 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900772 :py:obj:`Context.use_privatekey_file` propagates any exception raised by the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400773 passphrase callback.
774 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400775 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400776 def passphraseCallback(maxlen, verify, extra):
777 raise RuntimeError("Sorry, I am a fail.")
778
779 context = Context(TLSv1_METHOD)
780 context.set_passwd_cb(passphraseCallback)
781 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
782
783
784 def test_passwd_callback_false(self):
785 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900786 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400787 passphrase callback returns a false value.
788 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400789 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400790 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500791 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400792
793 context = Context(TLSv1_METHOD)
794 context.set_passwd_cb(passphraseCallback)
795 self.assertRaises(Error, context.use_privatekey_file, pemFile)
796
797
798 def test_passwd_callback_non_string(self):
799 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900800 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400801 passphrase callback returns a true non-string value.
802 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400803 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400804 def passphraseCallback(maxlen, verify, extra):
805 return 10
806
807 context = Context(TLSv1_METHOD)
808 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800809 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400810
811
812 def test_passwd_callback_too_long(self):
813 """
814 If the passphrase returned by the passphrase callback returns a string
815 longer than the indicated maximum length, it is truncated.
816 """
817 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400818 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400819 pemFile = self._write_encrypted_pem(passphrase)
820 def passphraseCallback(maxlen, verify, extra):
821 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400822 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400823
824 context = Context(TLSv1_METHOD)
825 context.set_passwd_cb(passphraseCallback)
826 # This shall succeed because the truncated result is the correct
827 # passphrase.
828 context.use_privatekey_file(pemFile)
829
830
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400831 def test_set_info_callback(self):
832 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900833 :py:obj:`Context.set_info_callback` accepts a callable which will be invoked
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400834 when certain information about an SSL connection is available.
835 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500836 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400837
838 clientSSL = Connection(Context(TLSv1_METHOD), client)
839 clientSSL.set_connect_state()
840
841 called = []
842 def info(conn, where, ret):
843 called.append((conn, where, ret))
844 context = Context(TLSv1_METHOD)
845 context.set_info_callback(info)
846 context.use_certificate(
847 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
848 context.use_privatekey(
849 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
850
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400851 serverSSL = Connection(context, server)
852 serverSSL.set_accept_state()
853
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500854 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400855
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500856 # The callback must always be called with a Connection instance as the
857 # first argument. It would probably be better to split this into
858 # separate tests for client and server side info callbacks so we could
859 # assert it is called with the right Connection instance. It would
860 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500861 notConnections = [
862 conn for (conn, where, ret) in called
863 if not isinstance(conn, Connection)]
864 self.assertEqual(
865 [], notConnections,
866 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400867
868
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400869 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400870 """
871 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400872 its :py:obj:`load_verify_locations` method with the given arguments.
873 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400874 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500875 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400876
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400877 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400878 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400879 # Require that the server certificate verify properly or the
880 # connection will fail.
881 clientContext.set_verify(
882 VERIFY_PEER,
883 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
884
885 clientSSL = Connection(clientContext, client)
886 clientSSL.set_connect_state()
887
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400888 serverContext = Context(TLSv1_METHOD)
889 serverContext.use_certificate(
890 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
891 serverContext.use_privatekey(
892 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
893
894 serverSSL = Connection(serverContext, server)
895 serverSSL.set_accept_state()
896
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400897 # Without load_verify_locations above, the handshake
898 # will fail:
899 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
900 # 'certificate verify failed')]
901 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400902
903 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400904 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400905
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500906
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400907 def test_load_verify_file(self):
908 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900909 :py:obj:`Context.load_verify_locations` accepts a file name and uses the
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400910 certificates within for verification purposes.
911 """
912 cafile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400913 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400914 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400915 fObj.close()
916
917 self._load_verify_locations_test(cafile)
918
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400919
920 def test_load_verify_invalid_file(self):
921 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900922 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when passed a
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400923 non-existent cafile.
924 """
925 clientContext = Context(TLSv1_METHOD)
926 self.assertRaises(
927 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400928
929
930 def test_load_verify_directory(self):
931 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900932 :py:obj:`Context.load_verify_locations` accepts a directory name and uses
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400933 the certificates within for verification purposes.
934 """
935 capath = self.mktemp()
936 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400937 # Hash values computed manually with c_rehash to avoid depending on
938 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
939 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500940 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400941 cafile = join(capath, name)
942 fObj = open(cafile, 'w')
943 fObj.write(cleartextCertificatePEM.decode('ascii'))
944 fObj.close()
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400945
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400946 self._load_verify_locations_test(None, capath)
947
948
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400949 def test_load_verify_locations_wrong_args(self):
950 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900951 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if called with
952 the wrong number of arguments or with non-:py:obj:`str` arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400953 """
954 context = Context(TLSv1_METHOD)
955 self.assertRaises(TypeError, context.load_verify_locations)
956 self.assertRaises(TypeError, context.load_verify_locations, object())
957 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
958 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
959
960
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400961 if platform == "win32":
962 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400963 "See LP#404343 and LP#404344."
964 else:
965 def test_set_default_verify_paths(self):
966 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900967 :py:obj:`Context.set_default_verify_paths` causes the platform-specific CA
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400968 certificate locations to be used for verification purposes.
969 """
970 # Testing this requires a server with a certificate signed by one of
971 # the CAs in the platform CA location. Getting one of those costs
972 # money. Fortunately (or unfortunately, depending on your
973 # perspective), it's easy to think of a public server on the
974 # internet which has such a certificate. Connecting to the network
975 # in a unit test is bad, but it's the only way I can think of to
976 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400977
Alex Gaynorb586da32014-11-15 09:22:21 -0800978 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
979 context = Context(TLSv1_METHOD)
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400980 context.set_default_verify_paths()
981 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +0200982 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400983 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400984
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400985 client = socket()
986 client.connect(('verisign.com', 443))
987 clientSSL = Connection(context, client)
988 clientSSL.set_connect_state()
989 clientSSL.do_handshake()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500990 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400991 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400992
993
994 def test_set_default_verify_paths_signature(self):
995 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900996 :py:obj:`Context.set_default_verify_paths` takes no arguments and raises
997 :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400998 """
999 context = Context(TLSv1_METHOD)
1000 self.assertRaises(TypeError, context.set_default_verify_paths, None)
1001 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
1002 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001003
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001004
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001005 def test_add_extra_chain_cert_invalid_cert(self):
1006 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001007 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if called with
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001008 other than one argument or if called with an object which is not an
Jonathan Ballet648875f2011-07-16 14:14:58 +09001009 instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001010 """
1011 context = Context(TLSv1_METHOD)
1012 self.assertRaises(TypeError, context.add_extra_chain_cert)
1013 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
1014 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
1015
1016
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001017 def _handshake_test(self, serverContext, clientContext):
1018 """
1019 Verify that a client and server created with the given contexts can
1020 successfully handshake and communicate.
1021 """
1022 serverSocket, clientSocket = socket_pair()
1023
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001024 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001025 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001026
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001027 client = Connection(clientContext, clientSocket)
1028 client.set_connect_state()
1029
1030 # Make them talk to each other.
1031 # self._interactInMemory(client, server)
1032 for i in range(3):
1033 for s in [client, server]:
1034 try:
1035 s.do_handshake()
1036 except WantReadError:
1037 pass
1038
1039
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001040 def test_set_verify_callback_connection_argument(self):
1041 """
1042 The first argument passed to the verify callback is the
1043 :py:class:`Connection` instance for which verification is taking place.
1044 """
1045 serverContext = Context(TLSv1_METHOD)
1046 serverContext.use_privatekey(
1047 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1048 serverContext.use_certificate(
1049 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1050 serverConnection = Connection(serverContext, None)
1051
1052 class VerifyCallback(object):
1053 def callback(self, connection, *args):
1054 self.connection = connection
1055 return 1
1056
1057 verify = VerifyCallback()
1058 clientContext = Context(TLSv1_METHOD)
1059 clientContext.set_verify(VERIFY_PEER, verify.callback)
1060 clientConnection = Connection(clientContext, None)
1061 clientConnection.set_connect_state()
1062
1063 self._handshakeInMemory(clientConnection, serverConnection)
1064
1065 self.assertIdentical(verify.connection, clientConnection)
1066
1067
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001068 def test_set_verify_callback_exception(self):
1069 """
1070 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1071 exception, verification fails and the exception is propagated to the
1072 caller of :py:obj:`Connection.do_handshake`.
1073 """
1074 serverContext = Context(TLSv1_METHOD)
1075 serverContext.use_privatekey(
1076 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1077 serverContext.use_certificate(
1078 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1079
1080 clientContext = Context(TLSv1_METHOD)
1081 def verify_callback(*args):
1082 raise Exception("silly verify failure")
1083 clientContext.set_verify(VERIFY_PEER, verify_callback)
1084
1085 exc = self.assertRaises(
1086 Exception, self._handshake_test, serverContext, clientContext)
1087 self.assertEqual("silly verify failure", str(exc))
1088
1089
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001090 def test_add_extra_chain_cert(self):
1091 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001092 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509` instance to add to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001093 the certificate chain.
1094
Jonathan Ballet648875f2011-07-16 14:14:58 +09001095 See :py:obj:`_create_certificate_chain` for the details of the certificate
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001096 chain tested.
1097
1098 The chain is tested by starting a server with scert and connecting
1099 to it with a client which trusts cacert and requires verification to
1100 succeed.
1101 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001102 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001103 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1104
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001105 # Dump the CA certificate to a file because that's the only way to load
1106 # it as a trusted CA in the client context.
1107 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001108 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001109 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001110 fObj.close()
1111
1112 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001113 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001114 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001115 fObj.close()
1116
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001117 # Create the server context
1118 serverContext = Context(TLSv1_METHOD)
1119 serverContext.use_privatekey(skey)
1120 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001121 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001122 serverContext.add_extra_chain_cert(icert)
1123
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001124 # Create the client
1125 clientContext = Context(TLSv1_METHOD)
1126 clientContext.set_verify(
1127 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001128 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001129
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001130 # Try it out.
1131 self._handshake_test(serverContext, clientContext)
1132
1133
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001134 def test_use_certificate_chain_file(self):
1135 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001136 :py:obj:`Context.use_certificate_chain_file` reads a certificate chain from
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001137 the specified file.
1138
1139 The chain is tested by starting a server with scert and connecting
1140 to it with a client which trusts cacert and requires verification to
1141 succeed.
1142 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001143 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001144 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1145
1146 # Write out the chain file.
1147 chainFile = self.mktemp()
Jean-Paul Calderoned8607982014-01-18 10:30:55 -05001148 fObj = open(chainFile, 'wb')
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001149 # Most specific to least general.
Jean-Paul Calderoned8607982014-01-18 10:30:55 -05001150 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1151 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1152 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001153 fObj.close()
1154
1155 serverContext = Context(TLSv1_METHOD)
1156 serverContext.use_certificate_chain_file(chainFile)
1157 serverContext.use_privatekey(skey)
1158
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001159 fObj = open('ca.pem', 'w')
1160 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001161 fObj.close()
1162
1163 clientContext = Context(TLSv1_METHOD)
1164 clientContext.set_verify(
1165 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001166 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001167
1168 self._handshake_test(serverContext, clientContext)
1169
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001170
1171 def test_use_certificate_chain_file_wrong_args(self):
1172 """
1173 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1174 if passed zero or more than one argument or when passed a non-byte
1175 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error` when
1176 passed a bad chain file name (for example, the name of a file which does
1177 not exist).
1178 """
1179 context = Context(TLSv1_METHOD)
1180 self.assertRaises(TypeError, context.use_certificate_chain_file)
1181 self.assertRaises(TypeError, context.use_certificate_chain_file, object())
1182 self.assertRaises(TypeError, context.use_certificate_chain_file, b"foo", object())
1183
1184 self.assertRaises(Error, context.use_certificate_chain_file, self.mktemp())
1185
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001186 # XXX load_client_ca
1187 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001188
1189 def test_get_verify_mode_wrong_args(self):
1190 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001191 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001192 arguments.
1193 """
1194 context = Context(TLSv1_METHOD)
1195 self.assertRaises(TypeError, context.get_verify_mode, None)
1196
1197
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001198 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001199 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001200 :py:obj:`Context.get_verify_mode` returns the verify mode flags previously
1201 passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001202 """
1203 context = Context(TLSv1_METHOD)
1204 self.assertEquals(context.get_verify_mode(), 0)
1205 context.set_verify(
1206 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1207 self.assertEquals(
1208 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1209
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001210
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001211 if not PY3:
1212 def test_set_verify_mode_long(self):
1213 """
1214 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1215 type :py:obj:`long` as well as :py:obj:`int`.
1216 """
1217 context = Context(TLSv1_METHOD)
1218 self.assertEquals(context.get_verify_mode(), 0)
1219 context.set_verify(
1220 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None)
1221 self.assertEquals(
1222 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1223
1224
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001225 def test_load_tmp_dh_wrong_args(self):
1226 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001227 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
1228 number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001229 """
1230 context = Context(TLSv1_METHOD)
1231 self.assertRaises(TypeError, context.load_tmp_dh)
1232 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1233 self.assertRaises(TypeError, context.load_tmp_dh, object())
1234
1235
1236 def test_load_tmp_dh_missing_file(self):
1237 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001238 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the specified file
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001239 does not exist.
1240 """
1241 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001242 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001243
1244
1245 def test_load_tmp_dh(self):
1246 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001247 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001248 specified file.
1249 """
1250 context = Context(TLSv1_METHOD)
1251 dhfilename = self.mktemp()
1252 dhfile = open(dhfilename, "w")
1253 dhfile.write(dhparam)
1254 dhfile.close()
1255 context.load_tmp_dh(dhfilename)
1256 # XXX What should I assert here? -exarkun
1257
1258
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001259 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001260 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001261 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001262 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001263 """
1264 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001265 for curve in get_elliptic_curves():
1266 # The only easily "assertable" thing is that it does not raise an
1267 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001268 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001269
1270
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001271 def test_set_cipher_list_bytes(self):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001272 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001273 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
1274 ciphers which connections created with the context object will be able
1275 to choose from.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001276 """
1277 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001278 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001279 conn = Connection(context, None)
1280 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001281
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001282
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001283 def test_set_cipher_list_text(self):
1284 """
1285 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
1286 the ciphers which connections created with the context object will be
1287 able to choose from.
1288 """
1289 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -05001290 context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001291 conn = Connection(context, None)
1292 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
1293
1294
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001295 def test_set_cipher_list_wrong_args(self):
1296 """
Jean-Paul Calderone17044832014-01-18 10:20:11 -05001297 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
1298 passed zero arguments or more than one argument or when passed a
1299 non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001300 passed an incorrect cipher list string.
1301 """
1302 context = Context(TLSv1_METHOD)
1303 self.assertRaises(TypeError, context.set_cipher_list)
1304 self.assertRaises(TypeError, context.set_cipher_list, object())
1305 self.assertRaises(TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object())
1306
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001307 self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001308
1309
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001310 def test_set_session_cache_mode_wrong_args(self):
1311 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001312 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1313 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001314 """
1315 context = Context(TLSv1_METHOD)
1316 self.assertRaises(TypeError, context.set_session_cache_mode)
1317 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1318
1319
1320 def test_get_session_cache_mode_wrong_args(self):
1321 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001322 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1323 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001324 """
1325 context = Context(TLSv1_METHOD)
1326 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1327
1328
1329 def test_session_cache_mode(self):
1330 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001331 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1332 cached. The setting can be retrieved via
1333 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001334 """
1335 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001336 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001337 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1338 self.assertEqual(SESS_CACHE_OFF, off)
1339 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1340
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001341 if not PY3:
1342 def test_session_cache_mode_long(self):
1343 """
1344 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1345 of type :py:obj:`long` as well as :py:obj:`int`.
1346 """
1347 context = Context(TLSv1_METHOD)
1348 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1349 self.assertEqual(
1350 SESS_CACHE_BOTH, context.get_session_cache_mode())
1351
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001352
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001353 def test_get_cert_store(self):
1354 """
1355 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store` instance.
1356 """
1357 context = Context(TLSv1_METHOD)
1358 store = context.get_cert_store()
1359 self.assertIsInstance(store, X509Store)
1360
1361
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001362
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001363class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1364 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001365 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
1366 :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001367 """
1368 def test_wrong_args(self):
1369 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001370 :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001371 with other than one argument.
1372 """
1373 context = Context(TLSv1_METHOD)
1374 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1375 self.assertRaises(
1376 TypeError, context.set_tlsext_servername_callback, 1, 2)
1377
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001378
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001379 def test_old_callback_forgotten(self):
1380 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001381 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001382 callback, the one it replaces is dereferenced.
1383 """
1384 def callback(connection):
1385 pass
1386
1387 def replacement(connection):
1388 pass
1389
1390 context = Context(TLSv1_METHOD)
1391 context.set_tlsext_servername_callback(callback)
1392
1393 tracker = ref(callback)
1394 del callback
1395
1396 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001397
1398 # One run of the garbage collector happens to work on CPython. PyPy
1399 # doesn't collect the underlying object until a second run for whatever
1400 # reason. That's fine, it still demonstrates our code has properly
1401 # dropped the reference.
1402 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001403 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001404
1405 callback = tracker()
1406 if callback is not None:
1407 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001408 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001409 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001410
1411
1412 def test_no_servername(self):
1413 """
1414 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001415 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
1416 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001417 """
1418 args = []
1419 def servername(conn):
1420 args.append((conn, conn.get_servername()))
1421 context = Context(TLSv1_METHOD)
1422 context.set_tlsext_servername_callback(servername)
1423
1424 # Lose our reference to it. The Context is responsible for keeping it
1425 # alive now.
1426 del servername
1427 collect()
1428
1429 # Necessary to actually accept the connection
1430 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1431 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1432
1433 # Do a little connection to trigger the logic
1434 server = Connection(context, None)
1435 server.set_accept_state()
1436
1437 client = Connection(Context(TLSv1_METHOD), None)
1438 client.set_connect_state()
1439
1440 self._interactInMemory(server, client)
1441
1442 self.assertEqual([(server, None)], args)
1443
1444
1445 def test_servername(self):
1446 """
1447 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +09001448 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
1449 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001450 """
1451 args = []
1452 def servername(conn):
1453 args.append((conn, conn.get_servername()))
1454 context = Context(TLSv1_METHOD)
1455 context.set_tlsext_servername_callback(servername)
1456
1457 # Necessary to actually accept the connection
1458 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1459 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1460
1461 # Do a little connection to trigger the logic
1462 server = Connection(context, None)
1463 server.set_accept_state()
1464
1465 client = Connection(Context(TLSv1_METHOD), None)
1466 client.set_connect_state()
1467 client.set_tlsext_host_name(b("foo1.example.com"))
1468
1469 self._interactInMemory(server, client)
1470
1471 self.assertEqual([(server, b("foo1.example.com"))], args)
1472
1473
1474
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001475class SessionTests(TestCase):
1476 """
1477 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1478 """
1479 def test_construction(self):
1480 """
1481 :py:class:`Session` can be constructed with no arguments, creating a new
1482 instance of that type.
1483 """
1484 new_session = Session()
1485 self.assertTrue(isinstance(new_session, Session))
1486
1487
1488 def test_construction_wrong_args(self):
1489 """
1490 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
1491 is raised.
1492 """
1493 self.assertRaises(TypeError, Session, 123)
1494 self.assertRaises(TypeError, Session, "hello")
1495 self.assertRaises(TypeError, Session, object())
1496
1497
1498
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001499class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05001500 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001501 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001502 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001503 # XXX get_peer_certificate -> None
1504 # XXX sock_shutdown
1505 # XXX master_key -> TypeError
1506 # XXX server_random -> TypeError
1507 # XXX state_string
1508 # XXX connect -> TypeError
1509 # XXX connect_ex -> TypeError
1510 # XXX set_connect_state -> TypeError
1511 # XXX set_accept_state -> TypeError
1512 # XXX renegotiate_pending
1513 # XXX do_handshake -> TypeError
1514 # XXX bio_read -> TypeError
1515 # XXX recv -> TypeError
1516 # XXX send -> TypeError
1517 # XXX bio_write -> TypeError
1518
Rick Deane15b1472009-07-09 15:53:42 -05001519 def test_type(self):
1520 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001521 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001522 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05001523 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001524 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05001525 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001526 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05001527
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001528
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001529 def test_get_context(self):
1530 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001531 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
1532 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001533 """
1534 context = Context(TLSv1_METHOD)
1535 connection = Connection(context, None)
1536 self.assertIdentical(connection.get_context(), context)
1537
1538
1539 def test_get_context_wrong_args(self):
1540 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001541 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001542 arguments.
1543 """
1544 connection = Connection(Context(TLSv1_METHOD), None)
1545 self.assertRaises(TypeError, connection.get_context, None)
1546
1547
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001548 def test_set_context_wrong_args(self):
1549 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001550 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
1551 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001552 than 1.
1553 """
1554 ctx = Context(TLSv1_METHOD)
1555 connection = Connection(ctx, None)
1556 self.assertRaises(TypeError, connection.set_context)
1557 self.assertRaises(TypeError, connection.set_context, object())
1558 self.assertRaises(TypeError, connection.set_context, "hello")
1559 self.assertRaises(TypeError, connection.set_context, 1)
1560 self.assertRaises(TypeError, connection.set_context, 1, 2)
1561 self.assertRaises(
1562 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
1563 self.assertIdentical(ctx, connection.get_context())
1564
1565
1566 def test_set_context(self):
1567 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001568 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001569 for the connection.
1570 """
1571 original = Context(SSLv23_METHOD)
1572 replacement = Context(TLSv1_METHOD)
1573 connection = Connection(original, None)
1574 connection.set_context(replacement)
1575 self.assertIdentical(replacement, connection.get_context())
1576 # Lose our references to the contexts, just in case the Connection isn't
1577 # properly managing its own contributions to their reference counts.
1578 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001579 collect()
1580
1581
1582 def test_set_tlsext_host_name_wrong_args(self):
1583 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001584 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001585 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09001586 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001587 """
1588 conn = Connection(Context(TLSv1_METHOD), None)
1589 self.assertRaises(TypeError, conn.set_tlsext_host_name)
1590 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
1591 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
1592 self.assertRaises(
1593 TypeError, conn.set_tlsext_host_name, b("with\0null"))
1594
1595 if version_info >= (3,):
1596 # On Python 3.x, don't accidentally implicitly convert from text.
1597 self.assertRaises(
1598 TypeError,
1599 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001600
1601
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001602 def test_get_servername_wrong_args(self):
1603 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001604 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001605 arguments.
1606 """
1607 connection = Connection(Context(TLSv1_METHOD), None)
1608 self.assertRaises(TypeError, connection.get_servername, object())
1609 self.assertRaises(TypeError, connection.get_servername, 1)
1610 self.assertRaises(TypeError, connection.get_servername, "hello")
1611
1612
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001613 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001614 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001615 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001616 immediate read.
1617 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001618 connection = Connection(Context(TLSv1_METHOD), None)
1619 self.assertEquals(connection.pending(), 0)
1620
1621
1622 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001623 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001624 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001625 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001626 connection = Connection(Context(TLSv1_METHOD), None)
1627 self.assertRaises(TypeError, connection.pending, None)
1628
1629
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001630 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001631 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001632 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001633 argument or with the wrong number of arguments.
1634 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001635 connection = Connection(Context(TLSv1_METHOD), socket())
1636 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001637 self.assertRaises(TypeError, connection.connect)
1638 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001639
1640
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001641 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001642 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001643 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001644 connect method raises it.
1645 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001646 client = socket()
1647 context = Context(TLSv1_METHOD)
1648 clientSSL = Connection(context, client)
1649 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04001650 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001651
1652
1653 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001654 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001655 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001656 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001657 port = socket()
1658 port.bind(('', 0))
1659 port.listen(3)
1660
1661 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001662 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
1663 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001664
1665
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001666 if platform == "darwin":
1667 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
1668 else:
1669 def test_connect_ex(self):
1670 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001671 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001672 errno instead of raising an exception.
1673 """
1674 port = socket()
1675 port.bind(('', 0))
1676 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001677
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001678 clientSSL = Connection(Context(TLSv1_METHOD), socket())
1679 clientSSL.setblocking(False)
1680 result = clientSSL.connect_ex(port.getsockname())
1681 expected = (EINPROGRESS, EWOULDBLOCK)
1682 self.assertTrue(
1683 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001684
1685
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001686 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001687 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001688 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001689 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001690 connection = Connection(Context(TLSv1_METHOD), socket())
1691 self.assertRaises(TypeError, connection.accept, None)
1692
1693
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001694 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001695 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001696 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
1697 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001698 connection originated from.
1699 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001700 ctx = Context(TLSv1_METHOD)
1701 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1702 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001703 port = socket()
1704 portSSL = Connection(ctx, port)
1705 portSSL.bind(('', 0))
1706 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001707
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001708 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001709
1710 # Calling portSSL.getsockname() here to get the server IP address sounds
1711 # great, but frequently fails on Windows.
1712 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001713
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001714 serverSSL, address = portSSL.accept()
1715
1716 self.assertTrue(isinstance(serverSSL, Connection))
1717 self.assertIdentical(serverSSL.get_context(), ctx)
1718 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001719
1720
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001721 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001722 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001723 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001724 number of arguments or with arguments other than integers.
1725 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001726 connection = Connection(Context(TLSv1_METHOD), None)
1727 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04001728 self.assertRaises(TypeError, connection.get_shutdown, None)
1729 self.assertRaises(TypeError, connection.set_shutdown)
1730 self.assertRaises(TypeError, connection.set_shutdown, None)
1731 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001732
1733
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001734 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001735 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001736 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001737 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001738 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001739 self.assertFalse(server.shutdown())
1740 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001741 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001742 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
1743 client.shutdown()
1744 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
1745 self.assertRaises(ZeroReturnError, server.recv, 1024)
1746 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001747
1748
Paul Aurichc85e0862015-01-08 08:34:33 -08001749 def test_shutdown_closed(self):
1750 """
1751 If the underlying socket is closed, :py:obj:`Connection.shutdown` propagates the
1752 write error from the low level write call.
1753 """
1754 server, client = self._loopback()
1755 server.sock_shutdown(2)
1756 exc = self.assertRaises(SysCallError, server.shutdown)
1757 if platform == "win32":
1758 self.assertEqual(exc.args[0], ESHUTDOWN)
1759 else:
1760 self.assertEqual(exc.args[0], EPIPE)
1761
1762
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001763 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001764 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001765 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001766 process.
1767 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001768 connection = Connection(Context(TLSv1_METHOD), socket())
1769 connection.set_shutdown(RECEIVED_SHUTDOWN)
1770 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1771
1772
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05001773 if not PY3:
1774 def test_set_shutdown_long(self):
1775 """
1776 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
1777 of type :py:obj:`long` as well as :py:obj:`int`.
1778 """
1779 connection = Connection(Context(TLSv1_METHOD), socket())
1780 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
1781 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1782
1783
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001784 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001785 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001786 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
1787 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001788 with any arguments.
1789 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001790 conn = Connection(Context(TLSv1_METHOD), None)
1791 self.assertRaises(TypeError, conn.get_app_data, None)
1792 self.assertRaises(TypeError, conn.set_app_data)
1793 self.assertRaises(TypeError, conn.set_app_data, None, None)
1794
1795
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001796 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001797 """
1798 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001799 :py:obj:`Connection.set_app_data` and later retrieved with
1800 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001801 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001802 conn = Connection(Context(TLSv1_METHOD), None)
1803 app_data = object()
1804 conn.set_app_data(app_data)
1805 self.assertIdentical(conn.get_app_data(), app_data)
1806
1807
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001808 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001809 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001810 :py:obj:`Connection.makefile` is not implemented and calling that method raises
1811 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001812 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001813 conn = Connection(Context(TLSv1_METHOD), None)
1814 self.assertRaises(NotImplementedError, conn.makefile)
1815
1816
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001817 def test_get_peer_cert_chain_wrong_args(self):
1818 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001819 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001820 arguments.
1821 """
1822 conn = Connection(Context(TLSv1_METHOD), None)
1823 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
1824 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
1825 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
1826 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
1827
1828
1829 def test_get_peer_cert_chain(self):
1830 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001831 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001832 the connected server returned for the certification verification.
1833 """
1834 chain = _create_certificate_chain()
1835 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1836
1837 serverContext = Context(TLSv1_METHOD)
1838 serverContext.use_privatekey(skey)
1839 serverContext.use_certificate(scert)
1840 serverContext.add_extra_chain_cert(icert)
1841 serverContext.add_extra_chain_cert(cacert)
1842 server = Connection(serverContext, None)
1843 server.set_accept_state()
1844
1845 # Create the client
1846 clientContext = Context(TLSv1_METHOD)
1847 clientContext.set_verify(VERIFY_NONE, verify_cb)
1848 client = Connection(clientContext, None)
1849 client.set_connect_state()
1850
1851 self._interactInMemory(client, server)
1852
1853 chain = client.get_peer_cert_chain()
1854 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001855 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001856 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001857 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001858 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001859 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001860 "Authority Certificate", chain[2].get_subject().CN)
1861
1862
1863 def test_get_peer_cert_chain_none(self):
1864 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001865 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001866 certificate chain.
1867 """
1868 ctx = Context(TLSv1_METHOD)
1869 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1870 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1871 server = Connection(ctx, None)
1872 server.set_accept_state()
1873 client = Connection(Context(TLSv1_METHOD), None)
1874 client.set_connect_state()
1875 self._interactInMemory(client, server)
1876 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001877
1878
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001879 def test_get_session_wrong_args(self):
1880 """
1881 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
1882 with any arguments.
1883 """
1884 ctx = Context(TLSv1_METHOD)
1885 server = Connection(ctx, None)
1886 self.assertRaises(TypeError, server.get_session, 123)
1887 self.assertRaises(TypeError, server.get_session, "hello")
1888 self.assertRaises(TypeError, server.get_session, object())
1889
1890
1891 def test_get_session_unconnected(self):
1892 """
1893 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
1894 an object which has not been connected.
1895 """
1896 ctx = Context(TLSv1_METHOD)
1897 server = Connection(ctx, None)
1898 session = server.get_session()
1899 self.assertIdentical(None, session)
1900
1901
1902 def test_server_get_session(self):
1903 """
1904 On the server side of a connection, :py:obj:`Connection.get_session`
1905 returns a :py:class:`Session` instance representing the SSL session for
1906 that connection.
1907 """
1908 server, client = self._loopback()
1909 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001910 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001911
1912
1913 def test_client_get_session(self):
1914 """
1915 On the client side of a connection, :py:obj:`Connection.get_session`
1916 returns a :py:class:`Session` instance representing the SSL session for
1917 that connection.
1918 """
1919 server, client = self._loopback()
1920 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001921 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001922
1923
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05001924 def test_set_session_wrong_args(self):
1925 """
1926 If called with an object that is not an instance of :py:class:`Session`,
1927 or with other than one argument, :py:obj:`Connection.set_session` raises
1928 :py:obj:`TypeError`.
1929 """
1930 ctx = Context(TLSv1_METHOD)
1931 connection = Connection(ctx, None)
1932 self.assertRaises(TypeError, connection.set_session)
1933 self.assertRaises(TypeError, connection.set_session, 123)
1934 self.assertRaises(TypeError, connection.set_session, "hello")
1935 self.assertRaises(TypeError, connection.set_session, object())
1936 self.assertRaises(
1937 TypeError, connection.set_session, Session(), Session())
1938
1939
1940 def test_client_set_session(self):
1941 """
1942 :py:obj:`Connection.set_session`, when used prior to a connection being
1943 established, accepts a :py:class:`Session` instance and causes an
1944 attempt to re-use the session it represents when the SSL handshake is
1945 performed.
1946 """
1947 key = load_privatekey(FILETYPE_PEM, server_key_pem)
1948 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
1949 ctx = Context(TLSv1_METHOD)
1950 ctx.use_privatekey(key)
1951 ctx.use_certificate(cert)
1952 ctx.set_session_id("unity-test")
1953
1954 def makeServer(socket):
1955 server = Connection(ctx, socket)
1956 server.set_accept_state()
1957 return server
1958
1959 originalServer, originalClient = self._loopback(
1960 serverFactory=makeServer)
1961 originalSession = originalClient.get_session()
1962
1963 def makeClient(socket):
1964 client = self._loopbackClientFactory(socket)
1965 client.set_session(originalSession)
1966 return client
1967 resumedServer, resumedClient = self._loopback(
1968 serverFactory=makeServer,
1969 clientFactory=makeClient)
1970
1971 # This is a proxy: in general, we have no access to any unique
1972 # identifier for the session (new enough versions of OpenSSL expose a
1973 # hash which could be usable, but "new enough" is very, very new).
1974 # Instead, exploit the fact that the master key is re-used if the
1975 # session is re-used. As long as the master key for the two connections
1976 # is the same, the session was re-used!
1977 self.assertEqual(
1978 originalServer.master_key(), resumedServer.master_key())
1979
1980
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05001981 def test_set_session_wrong_method(self):
1982 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05001983 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
1984 instance associated with a context using a different SSL method than the
1985 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
1986 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05001987 """
1988 key = load_privatekey(FILETYPE_PEM, server_key_pem)
1989 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
1990 ctx = Context(TLSv1_METHOD)
1991 ctx.use_privatekey(key)
1992 ctx.use_certificate(cert)
1993 ctx.set_session_id("unity-test")
1994
1995 def makeServer(socket):
1996 server = Connection(ctx, socket)
1997 server.set_accept_state()
1998 return server
1999
2000 originalServer, originalClient = self._loopback(
2001 serverFactory=makeServer)
2002 originalSession = originalClient.get_session()
2003
2004 def makeClient(socket):
2005 # Intentionally use a different, incompatible method here.
2006 client = Connection(Context(SSLv3_METHOD), socket)
2007 client.set_connect_state()
2008 client.set_session(originalSession)
2009 return client
2010
2011 self.assertRaises(
2012 Error,
2013 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2014
2015
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002016 def test_wantWriteError(self):
2017 """
2018 :py:obj:`Connection` methods which generate output raise
2019 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2020 fail indicating a should-write state.
2021 """
2022 client_socket, server_socket = socket_pair()
2023 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002024 # anything. Only write a single byte at a time so we can be sure we
2025 # completely fill the buffer. Even though the socket API is allowed to
2026 # signal a short write via its return value it seems this doesn't
2027 # always happen on all platforms (FreeBSD and OS X particular) for the
2028 # very last bit of available buffer space.
2029 msg = b"x"
2030 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002031 try:
2032 client_socket.send(msg)
2033 except error as e:
2034 if e.errno == EWOULDBLOCK:
2035 break
2036 raise
2037 else:
2038 self.fail(
2039 "Failed to fill socket buffer, cannot test BIO want write")
2040
2041 ctx = Context(TLSv1_METHOD)
2042 conn = Connection(ctx, client_socket)
2043 # Client's speak first, so make it an SSL client
2044 conn.set_connect_state()
2045 self.assertRaises(WantWriteError, conn.do_handshake)
2046
2047 # XXX want_read
2048
Fedor Brunner416f4a12014-03-28 13:18:38 +01002049 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002050 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002051 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2052 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002053 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002054 ctx = Context(TLSv1_METHOD)
2055 connection = Connection(ctx, None)
2056 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002057
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002058
Fedor Brunner416f4a12014-03-28 13:18:38 +01002059 def test_get_peer_finished_before_connect(self):
2060 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002061 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2062 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002063 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002064 ctx = Context(TLSv1_METHOD)
2065 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002066 self.assertEqual(connection.get_peer_finished(), None)
2067
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002068
Fedor Brunner416f4a12014-03-28 13:18:38 +01002069 def test_get_finished(self):
2070 """
2071 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002072 message send from client, or server. Finished messages are send during
2073 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002074 """
2075
Fedor Brunner5747b932014-03-05 14:22:34 +01002076 server, client = self._loopback()
2077
2078 self.assertNotEqual(server.get_finished(), None)
2079 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002080
Jean-Paul Calderoned979f232014-03-30 11:58:00 -04002081
Fedor Brunner416f4a12014-03-28 13:18:38 +01002082 def test_get_peer_finished(self):
2083 """
2084 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002085 message received from client, or server. Finished messages are send
2086 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002087 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002088 server, client = self._loopback()
2089
2090 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002091 self.assertTrue(len(server.get_peer_finished()) > 0)
2092
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002093
Fedor Brunner416f4a12014-03-28 13:18:38 +01002094 def test_tls_finished_message_symmetry(self):
2095 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002096 The TLS Finished message send by server must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002097 received by client.
2098
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002099 The TLS Finished message send by client must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002100 received by server.
2101 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002102 server, client = self._loopback()
2103
Fedor Brunner5747b932014-03-05 14:22:34 +01002104 self.assertEqual(server.get_finished(), client.get_peer_finished())
2105 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002106
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002107
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002108 def test_get_cipher_name_before_connect(self):
2109 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002110 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2111 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002112 """
2113 ctx = Context(TLSv1_METHOD)
2114 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002115 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002116
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002117
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002118 def test_get_cipher_name(self):
2119 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002120 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2121 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002122 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002123 server, client = self._loopback()
2124 server_cipher_name, client_cipher_name = \
2125 server.get_cipher_name(), client.get_cipher_name()
2126
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002127 self.assertIsInstance(server_cipher_name, text_type)
2128 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002129
2130 self.assertEqual(server_cipher_name, client_cipher_name)
2131
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002132
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002133 def test_get_cipher_version_before_connect(self):
2134 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002135 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2136 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002137 """
2138 ctx = Context(TLSv1_METHOD)
2139 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002140 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002141
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002142
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002143 def test_get_cipher_version(self):
2144 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002145 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2146 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002147 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002148 server, client = self._loopback()
2149 server_cipher_version, client_cipher_version = \
2150 server.get_cipher_version(), client.get_cipher_version()
2151
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002152 self.assertIsInstance(server_cipher_version, text_type)
2153 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002154
2155 self.assertEqual(server_cipher_version, client_cipher_version)
2156
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002157
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002158 def test_get_cipher_bits_before_connect(self):
2159 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002160 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2161 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002162 """
2163 ctx = Context(TLSv1_METHOD)
2164 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002165 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002166
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002167
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002168 def test_get_cipher_bits(self):
2169 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002170 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2171 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002172 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002173 server, client = self._loopback()
2174 server_cipher_bits, client_cipher_bits = \
2175 server.get_cipher_bits(), client.get_cipher_bits()
2176
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002177 self.assertIsInstance(server_cipher_bits, int)
2178 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002179
2180 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002181
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002182
2183
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002184class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002185 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002186 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002187 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002188 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002189 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002190 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002191 arguments.
2192 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002193 connection = Connection(Context(TLSv1_METHOD), None)
2194 self.assertRaises(TypeError, connection.get_cipher_list, None)
2195
2196
2197 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002198 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002199 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2200 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002201 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002202 connection = Connection(Context(TLSv1_METHOD), None)
2203 ciphers = connection.get_cipher_list()
2204 self.assertTrue(isinstance(ciphers, list))
2205 for cipher in ciphers:
2206 self.assertTrue(isinstance(cipher, str))
2207
2208
2209
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002210class ConnectionSendTests(TestCase, _LoopbackMixin):
2211 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002212 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002213 """
2214 def test_wrong_args(self):
2215 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002216 When called with arguments other than string argument for its first
2217 parameter or more than two arguments, :py:obj:`Connection.send` raises
2218 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002219 """
2220 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002221 self.assertRaises(TypeError, connection.send)
2222 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002223 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002224
2225
2226 def test_short_bytes(self):
2227 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002228 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002229 and returns the number of bytes sent.
2230 """
2231 server, client = self._loopback()
2232 count = server.send(b('xy'))
2233 self.assertEquals(count, 2)
2234 self.assertEquals(client.recv(2), b('xy'))
2235
2236 try:
2237 memoryview
2238 except NameError:
2239 "cannot test sending memoryview without memoryview"
2240 else:
2241 def test_short_memoryview(self):
2242 """
2243 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002244 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002245 bytes sent.
2246 """
2247 server, client = self._loopback()
2248 count = server.send(memoryview(b('xy')))
2249 self.assertEquals(count, 2)
2250 self.assertEquals(client.recv(2), b('xy'))
2251
2252
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002253 try:
2254 buffer
2255 except NameError:
2256 "cannot test sending buffer without buffer"
2257 else:
2258 def test_short_buffer(self):
2259 """
2260 When passed a buffer containing a small number of bytes,
2261 :py:obj:`Connection.send` transmits all of them and returns the number of
2262 bytes sent.
2263 """
2264 server, client = self._loopback()
2265 count = server.send(buffer(b('xy')))
2266 self.assertEquals(count, 2)
2267 self.assertEquals(client.recv(2), b('xy'))
2268
2269
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002270
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002271class ConnectionSendallTests(TestCase, _LoopbackMixin):
2272 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002273 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002274 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002275 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002276 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002277 When called with arguments other than a string argument for its first
2278 parameter or with more than two arguments, :py:obj:`Connection.sendall`
2279 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002280 """
2281 connection = Connection(Context(TLSv1_METHOD), None)
2282 self.assertRaises(TypeError, connection.sendall)
2283 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002284 self.assertRaises(
2285 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002286
2287
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002288 def test_short(self):
2289 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002290 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002291 it.
2292 """
2293 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04002294 server.sendall(b('x'))
2295 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002296
2297
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002298 try:
2299 memoryview
2300 except NameError:
2301 "cannot test sending memoryview without memoryview"
2302 else:
2303 def test_short_memoryview(self):
2304 """
2305 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002306 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002307 """
2308 server, client = self._loopback()
2309 server.sendall(memoryview(b('x')))
2310 self.assertEquals(client.recv(1), b('x'))
2311
2312
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002313 try:
2314 buffer
2315 except NameError:
2316 "cannot test sending buffers without buffers"
2317 else:
2318 def test_short_buffers(self):
2319 """
2320 When passed a buffer containing a small number of bytes,
2321 :py:obj:`Connection.sendall` transmits all of them.
2322 """
2323 server, client = self._loopback()
2324 server.sendall(buffer(b('x')))
2325 self.assertEquals(client.recv(1), b('x'))
2326
2327
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002328 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002329 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002330 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002331 it even if this requires multiple calls of an underlying write function.
2332 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002333 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04002334 # Should be enough, underlying SSL_write should only do 16k at a time.
2335 # On Windows, after 32k of bytes the write will block (forever - because
2336 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04002337 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002338 server.sendall(message)
2339 accum = []
2340 received = 0
2341 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04002342 data = client.recv(1024)
2343 accum.append(data)
2344 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04002345 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002346
2347
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002348 def test_closed(self):
2349 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002350 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002351 write error from the low level write call.
2352 """
2353 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04002354 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002355 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02002356 if platform == "win32":
2357 self.assertEqual(exc.args[0], ESHUTDOWN)
2358 else:
2359 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002360
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002361
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002362
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002363class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
2364 """
2365 Tests for SSL renegotiation APIs.
2366 """
2367 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002368 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002369 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002370 arguments.
2371 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002372 connection = Connection(Context(TLSv1_METHOD), None)
2373 self.assertRaises(TypeError, connection.renegotiate, None)
2374
2375
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002376 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002377 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002378 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002379 any arguments.
2380 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002381 connection = Connection(Context(TLSv1_METHOD), None)
2382 self.assertRaises(TypeError, connection.total_renegotiations, None)
2383
2384
2385 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002386 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002387 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002388 renegotiations have happened.
2389 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002390 connection = Connection(Context(TLSv1_METHOD), None)
2391 self.assertEquals(connection.total_renegotiations(), 0)
2392
2393
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002394# def test_renegotiate(self):
2395# """
2396# """
2397# server, client = self._loopback()
2398
2399# server.send("hello world")
2400# self.assertEquals(client.recv(len("hello world")), "hello world")
2401
2402# self.assertEquals(server.total_renegotiations(), 0)
2403# self.assertTrue(server.renegotiate())
2404
2405# server.setblocking(False)
2406# client.setblocking(False)
2407# while server.renegotiate_pending():
2408# client.do_handshake()
2409# server.do_handshake()
2410
2411# self.assertEquals(server.total_renegotiations(), 1)
2412
2413
2414
2415
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002416class ErrorTests(TestCase):
2417 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002418 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002419 """
2420 def test_type(self):
2421 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002422 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002423 """
2424 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05002425 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05002426
2427
2428
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002429class ConstantsTests(TestCase):
2430 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002431 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002432
2433 These are values defined by OpenSSL intended only to be used as flags to
2434 OpenSSL APIs. The only assertions it seems can be made about them is
2435 their values.
2436 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002437 # unittest.TestCase has no skip mechanism
2438 if OP_NO_QUERY_MTU is not None:
2439 def test_op_no_query_mtu(self):
2440 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002441 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002442 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002443 """
2444 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
2445 else:
2446 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002447
2448
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002449 if OP_COOKIE_EXCHANGE is not None:
2450 def test_op_cookie_exchange(self):
2451 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002452 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002453 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002454 """
2455 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
2456 else:
2457 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002458
2459
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002460 if OP_NO_TICKET is not None:
2461 def test_op_no_ticket(self):
2462 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002463 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002464 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002465 """
2466 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04002467 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002468 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05002469
2470
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002471 if OP_NO_COMPRESSION is not None:
2472 def test_op_no_compression(self):
2473 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002474 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
2475 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002476 """
2477 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
2478 else:
2479 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
2480
2481
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002482 def test_sess_cache_off(self):
2483 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002484 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
2485 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002486 """
2487 self.assertEqual(0x0, SESS_CACHE_OFF)
2488
2489
2490 def test_sess_cache_client(self):
2491 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002492 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
2493 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002494 """
2495 self.assertEqual(0x1, SESS_CACHE_CLIENT)
2496
2497
2498 def test_sess_cache_server(self):
2499 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002500 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
2501 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002502 """
2503 self.assertEqual(0x2, SESS_CACHE_SERVER)
2504
2505
2506 def test_sess_cache_both(self):
2507 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002508 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
2509 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002510 """
2511 self.assertEqual(0x3, SESS_CACHE_BOTH)
2512
2513
2514 def test_sess_cache_no_auto_clear(self):
2515 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002516 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
2517 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
2518 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002519 """
2520 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
2521
2522
2523 def test_sess_cache_no_internal_lookup(self):
2524 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002525 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
2526 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
2527 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002528 """
2529 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
2530
2531
2532 def test_sess_cache_no_internal_store(self):
2533 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002534 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
2535 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
2536 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002537 """
2538 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
2539
2540
2541 def test_sess_cache_no_internal(self):
2542 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002543 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
2544 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
2545 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002546 """
2547 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
2548
2549
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04002550
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002551class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05002552 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002553 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05002554 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002555 def _server(self, sock):
2556 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002557 Create a new server-side SSL :py:obj:`Connection` object wrapped around
2558 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002559 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002560 # Create the server side Connection. This is mostly setup boilerplate
2561 # - use TLSv1, use a particular certificate, etc.
2562 server_ctx = Context(TLSv1_METHOD)
2563 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2564 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2565 server_store = server_ctx.get_cert_store()
2566 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2567 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2568 server_ctx.check_privatekey()
2569 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002570 # Here the Connection is actually created. If None is passed as the 2nd
2571 # parameter, it indicates a memory BIO should be created.
2572 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002573 server_conn.set_accept_state()
2574 return server_conn
2575
2576
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002577 def _client(self, sock):
2578 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002579 Create a new client-side SSL :py:obj:`Connection` object wrapped around
2580 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002581 """
2582 # Now create the client side Connection. Similar boilerplate to the
2583 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002584 client_ctx = Context(TLSv1_METHOD)
2585 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2586 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2587 client_store = client_ctx.get_cert_store()
2588 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
2589 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
2590 client_ctx.check_privatekey()
2591 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002592 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002593 client_conn.set_connect_state()
2594 return client_conn
2595
2596
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002597 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002598 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002599 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002600 reading from the output of each and writing those bytes to the input of
2601 the other and in this way establish a connection and exchange
2602 application-level bytes with each other.
2603 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002604 server_conn = self._server(None)
2605 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002606
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002607 # There should be no key or nonces yet.
2608 self.assertIdentical(server_conn.master_key(), None)
2609 self.assertIdentical(server_conn.client_random(), None)
2610 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002611
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002612 # First, the handshake needs to happen. We'll deliver bytes back and
2613 # forth between the client and server until neither of them feels like
2614 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002615 self.assertIdentical(
2616 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002617
2618 # Now that the handshake is done, there should be a key and nonces.
2619 self.assertNotIdentical(server_conn.master_key(), None)
2620 self.assertNotIdentical(server_conn.client_random(), None)
2621 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04002622 self.assertEquals(server_conn.client_random(), client_conn.client_random())
2623 self.assertEquals(server_conn.server_random(), client_conn.server_random())
2624 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
2625 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002626
2627 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002628 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05002629
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002630 server_conn.write(important_message)
2631 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002632 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002633 (client_conn, important_message))
2634
2635 client_conn.write(important_message[::-1])
2636 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002637 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002638 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05002639
2640
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002641 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05002642 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002643 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002644
2645 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09002646 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002647 this test fails, there must be a problem outside the memory BIO
2648 code, as no memory BIO is involved here). Even though this isn't a
2649 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05002650 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04002651 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05002652
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002653 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05002654 client_conn.send(important_message)
2655 msg = server_conn.recv(1024)
2656 self.assertEqual(msg, important_message)
2657
2658 # Again in the other direction, just for fun.
2659 important_message = important_message[::-1]
2660 server_conn.send(important_message)
2661 msg = client_conn.recv(1024)
2662 self.assertEqual(msg, important_message)
2663
2664
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04002665 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05002666 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002667 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
2668 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05002669 """
2670 context = Context(SSLv3_METHOD)
2671 client = socket()
2672 clientSSL = Connection(context, client)
2673 self.assertRaises( TypeError, clientSSL.bio_read, 100)
2674 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04002675 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002676
2677
2678 def test_outgoingOverflow(self):
2679 """
2680 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002681 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002682 returned and that many bytes from the beginning of the input can be
2683 read from the other end of the connection.
2684 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002685 server = self._server(None)
2686 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002687
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002688 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002689
2690 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002691 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002692 # Sanity check. We're trying to test what happens when the entire
2693 # input can't be sent. If the entire input was sent, this test is
2694 # meaningless.
2695 self.assertTrue(sent < size)
2696
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002697 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002698 self.assertIdentical(receiver, server)
2699
2700 # We can rely on all of these bytes being received at once because
2701 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
2702 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002703
2704
2705 def test_shutdown(self):
2706 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002707 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
2708 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002709 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002710 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002711 server.bio_shutdown()
2712 e = self.assertRaises(Error, server.recv, 1024)
2713 # We don't want WantReadError or ZeroReturnError or anything - it's a
2714 # handshake failure.
2715 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002716
2717
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002718 def test_unexpectedEndOfFile(self):
2719 """
2720 If the connection is lost before an orderly SSL shutdown occurs,
2721 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
2722 "Unexpected EOF".
2723 """
2724 server_conn, client_conn = self._loopback()
2725 client_conn.sock_shutdown(SHUT_RDWR)
2726 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
2727 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
2728
2729
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002730 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002731 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002732 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 -04002733
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002734 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002735 before the client and server are connected to each other. This
2736 function should specify a list of CAs for the server to send to the
2737 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09002738 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002739 times.
2740 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002741 server = self._server(None)
2742 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002743 self.assertEqual(client.get_client_ca_list(), [])
2744 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002745 ctx = server.get_context()
2746 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002747 self.assertEqual(client.get_client_ca_list(), [])
2748 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002749 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002750 self.assertEqual(client.get_client_ca_list(), expected)
2751 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002752
2753
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002754 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002755 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002756 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002757 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002758 """
2759 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002760 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
2761 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
2762 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002763
2764
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002765 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002766 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002767 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002768 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09002769 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002770 after the connection is set up.
2771 """
2772 def no_ca(ctx):
2773 ctx.set_client_ca_list([])
2774 return []
2775 self._check_client_ca_list(no_ca)
2776
2777
2778 def test_set_one_ca_list(self):
2779 """
2780 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002781 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002782 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002783 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002784 X509Name after the connection is set up.
2785 """
2786 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2787 cadesc = cacert.get_subject()
2788 def single_ca(ctx):
2789 ctx.set_client_ca_list([cadesc])
2790 return [cadesc]
2791 self._check_client_ca_list(single_ca)
2792
2793
2794 def test_set_multiple_ca_list(self):
2795 """
2796 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002797 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002798 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002799 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002800 X509Names after the connection is set up.
2801 """
2802 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2803 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2804
2805 sedesc = secert.get_subject()
2806 cldesc = clcert.get_subject()
2807
2808 def multiple_ca(ctx):
2809 L = [sedesc, cldesc]
2810 ctx.set_client_ca_list(L)
2811 return L
2812 self._check_client_ca_list(multiple_ca)
2813
2814
2815 def test_reset_ca_list(self):
2816 """
2817 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09002818 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002819 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002820 """
2821 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2822 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2823 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2824
2825 cadesc = cacert.get_subject()
2826 sedesc = secert.get_subject()
2827 cldesc = clcert.get_subject()
2828
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002829 def changed_ca(ctx):
2830 ctx.set_client_ca_list([sedesc, cldesc])
2831 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002832 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002833 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002834
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002835
2836 def test_mutated_ca_list(self):
2837 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002838 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002839 afterwards, this does not affect the list of CA names sent to the
2840 client.
2841 """
2842 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2843 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2844
2845 cadesc = cacert.get_subject()
2846 sedesc = secert.get_subject()
2847
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002848 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002849 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002850 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002851 L.append(sedesc)
2852 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002853 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002854
2855
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002856 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002857 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002858 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002859 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002860 """
2861 ctx = Context(TLSv1_METHOD)
2862 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002863 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002864 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002865 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002866
2867
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002868 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002869 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002870 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09002871 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002872 """
2873 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2874 cadesc = cacert.get_subject()
2875 def single_ca(ctx):
2876 ctx.add_client_ca(cacert)
2877 return [cadesc]
2878 self._check_client_ca_list(single_ca)
2879
2880
2881 def test_multiple_add_client_ca(self):
2882 """
2883 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09002884 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002885 """
2886 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2887 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2888
2889 cadesc = cacert.get_subject()
2890 sedesc = secert.get_subject()
2891
2892 def multiple_ca(ctx):
2893 ctx.add_client_ca(cacert)
2894 ctx.add_client_ca(secert)
2895 return [cadesc, sedesc]
2896 self._check_client_ca_list(multiple_ca)
2897
2898
2899 def test_set_and_add_client_ca(self):
2900 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002901 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
2902 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002903 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002904 """
2905 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2906 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2907 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2908
2909 cadesc = cacert.get_subject()
2910 sedesc = secert.get_subject()
2911 cldesc = clcert.get_subject()
2912
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002913 def mixed_set_add_ca(ctx):
2914 ctx.set_client_ca_list([cadesc, sedesc])
2915 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002916 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002917 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002918
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002919
2920 def test_set_after_add_client_ca(self):
2921 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002922 A call to :py:obj:`Context.set_client_ca_list` after a call to
2923 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002924 call with the names specified by the latter cal.
2925 """
2926 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2927 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2928 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2929
2930 cadesc = cacert.get_subject()
2931 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002932
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002933 def set_replaces_add_ca(ctx):
2934 ctx.add_client_ca(clcert)
2935 ctx.set_client_ca_list([cadesc])
2936 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002937 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002938 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002939
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002940
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002941
2942class ConnectionBIOTests(TestCase):
2943 """
2944 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
2945 """
2946 def test_wantReadError(self):
2947 """
2948 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
2949 if there are no bytes available to be read from the BIO.
2950 """
2951 ctx = Context(TLSv1_METHOD)
2952 conn = Connection(ctx, None)
2953 self.assertRaises(WantReadError, conn.bio_read, 1024)
2954
2955
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002956 def test_buffer_size(self):
2957 """
2958 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
2959 number of bytes to read and return.
2960 """
2961 ctx = Context(TLSv1_METHOD)
2962 conn = Connection(ctx, None)
2963 conn.set_connect_state()
2964 try:
2965 conn.do_handshake()
2966 except WantReadError:
2967 pass
2968 data = conn.bio_read(2)
2969 self.assertEqual(2, len(data))
2970
2971
2972 if not PY3:
2973 def test_buffer_size_long(self):
2974 """
2975 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
2976 :py:obj:`long` as well as :py:obj:`int`.
2977 """
2978 ctx = Context(TLSv1_METHOD)
2979 conn = Connection(ctx, None)
2980 conn.set_connect_state()
2981 try:
2982 conn.do_handshake()
2983 except WantReadError:
2984 pass
2985 data = conn.bio_read(long(2))
2986 self.assertEqual(2, len(data))
2987
2988
2989
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002990
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04002991class InfoConstantTests(TestCase):
2992 """
2993 Tests for assorted constants exposed for use in info callbacks.
2994 """
2995 def test_integers(self):
2996 """
2997 All of the info constants are integers.
2998
2999 This is a very weak test. It would be nice to have one that actually
3000 verifies that as certain info events happen, the value passed to the
3001 info callback matches up with the constant exposed by OpenSSL.SSL.
3002 """
3003 for const in [
3004 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3005 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3006 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3007 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3008 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
3009 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
3010
3011 self.assertTrue(isinstance(const, int))
3012
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003013
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003014if __name__ == '__main__':
3015 main()