blob: 2686d120d7106125a28a61f740ff9daaf3eafc0b [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 Calderonebef4f4c2014-02-02 18:13:31 -050017from six import PY3, 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
23
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040024from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
25from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040026from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040027from OpenSSL.SSL import (
28 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
29 TLSv1_1_METHOD, TLSv1_2_METHOD)
30from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040031from OpenSSL.SSL import (
32 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040033
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040034from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050035 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
36 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
37 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
Alex Gaynor807853c2014-01-17 13:03:27 -060038from OpenSSL.SSL import NID_X9_62_prime256v1, _Cryptography_HAS_EC
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050039
40from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070041 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050042from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070043 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040044
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050045from OpenSSL.test.util import TestCase, b
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040046from OpenSSL.test.test_crypto import (
47 cleartextCertificatePEM, cleartextPrivateKeyPEM)
48from OpenSSL.test.test_crypto import (
49 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
50 root_cert_pem)
51
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050052try:
53 from OpenSSL.SSL import OP_NO_QUERY_MTU
54except ImportError:
55 OP_NO_QUERY_MTU = None
56try:
57 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
58except ImportError:
59 OP_COOKIE_EXCHANGE = None
60try:
61 from OpenSSL.SSL import OP_NO_TICKET
62except ImportError:
63 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040064
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040065try:
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -040066 from OpenSSL.SSL import OP_NO_COMPRESSION
67except ImportError:
68 OP_NO_COMPRESSION = None
69
70try:
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040071 from OpenSSL.SSL import MODE_RELEASE_BUFFERS
72except ImportError:
73 MODE_RELEASE_BUFFERS = None
74
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040075try:
76 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
77except ImportError:
78 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
79
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040080from OpenSSL.SSL import (
81 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
82 SSL_ST_OK, SSL_ST_RENEGOTIATE,
83 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
84 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
85 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
86 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040087
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040088# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
89# to use)
90dhparam = """\
91-----BEGIN DH PARAMETERS-----
92MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
93-----END DH PARAMETERS-----
94"""
95
96
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040097def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040098 return ok
99
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400100
Rick Deanb1ccd562009-07-09 23:52:39 -0500101def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400102 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400103 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400104 """
105 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500106 port = socket()
107 port.bind(('', 0))
108 port.listen(1)
109 client = socket()
110 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400111 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400112 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500113 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500114
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400115 # Let's pass some unencrypted data to make sure our socket connection is
116 # fine. Just one byte, so we don't have to worry about buffers getting
117 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400118 server.send(b("x"))
119 assert client.recv(1024) == b("x")
120 client.send(b("y"))
121 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500122
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400123 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400124 server.setblocking(False)
125 client.setblocking(False)
126
Rick Deanb1ccd562009-07-09 23:52:39 -0500127 return (server, client)
128
129
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400130
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400131def handshake(client, server):
132 conns = [client, server]
133 while conns:
134 for conn in conns:
135 try:
136 conn.do_handshake()
137 except WantReadError:
138 pass
139 else:
140 conns.remove(conn)
141
142
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400143def _create_certificate_chain():
144 """
145 Construct and return a chain of certificates.
146
147 1. A new self-signed certificate authority certificate (cacert)
148 2. A new intermediate certificate signed by cacert (icert)
149 3. A new server certificate signed by icert (scert)
150 """
151 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
152
153 # Step 1
154 cakey = PKey()
155 cakey.generate_key(TYPE_RSA, 512)
156 cacert = X509()
157 cacert.get_subject().commonName = "Authority Certificate"
158 cacert.set_issuer(cacert.get_subject())
159 cacert.set_pubkey(cakey)
160 cacert.set_notBefore(b("20000101000000Z"))
161 cacert.set_notAfter(b("20200101000000Z"))
162 cacert.add_extensions([caext])
163 cacert.set_serial_number(0)
164 cacert.sign(cakey, "sha1")
165
166 # Step 2
167 ikey = PKey()
168 ikey.generate_key(TYPE_RSA, 512)
169 icert = X509()
170 icert.get_subject().commonName = "Intermediate Certificate"
171 icert.set_issuer(cacert.get_subject())
172 icert.set_pubkey(ikey)
173 icert.set_notBefore(b("20000101000000Z"))
174 icert.set_notAfter(b("20200101000000Z"))
175 icert.add_extensions([caext])
176 icert.set_serial_number(0)
177 icert.sign(cakey, "sha1")
178
179 # Step 3
180 skey = PKey()
181 skey.generate_key(TYPE_RSA, 512)
182 scert = X509()
183 scert.get_subject().commonName = "Server Certificate"
184 scert.set_issuer(icert.get_subject())
185 scert.set_pubkey(skey)
186 scert.set_notBefore(b("20000101000000Z"))
187 scert.set_notAfter(b("20200101000000Z"))
188 scert.add_extensions([
189 X509Extension(b('basicConstraints'), True, b('CA:false'))])
190 scert.set_serial_number(0)
191 scert.sign(ikey, "sha1")
192
193 return [(cakey, cacert), (ikey, icert), (skey, scert)]
194
195
196
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400197class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400198 """
199 Helper mixin which defines methods for creating a connected socket pair and
200 for forcing two connected SSL sockets to talk to each other via memory BIOs.
201 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500202 def _loopbackClientFactory(self, socket):
203 client = Connection(Context(TLSv1_METHOD), socket)
204 client.set_connect_state()
205 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400206
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500207
208 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400209 ctx = Context(TLSv1_METHOD)
210 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
211 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500212 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400213 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500214 return server
215
216
217 def _loopback(self, serverFactory=None, clientFactory=None):
218 if serverFactory is None:
219 serverFactory = self._loopbackServerFactory
220 if clientFactory is None:
221 clientFactory = self._loopbackClientFactory
222
223 (server, client) = socket_pair()
224 server = serverFactory(server)
225 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400226
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400227 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400228
229 server.setblocking(True)
230 client.setblocking(True)
231 return server, client
232
233
234 def _interactInMemory(self, client_conn, server_conn):
235 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900236 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400237 objects. Copy bytes back and forth between their send/receive buffers
238 for as long as there is anything to copy. When there is nothing more
Jonathan Ballet648875f2011-07-16 14:14:58 +0900239 to copy, return :py:obj:`None`. If one of them actually manages to deliver
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400240 some application bytes, return a two-tuple of the connection from which
241 the bytes were read and the bytes themselves.
242 """
243 wrote = True
244 while wrote:
245 # Loop until neither side has anything to say
246 wrote = False
247
248 # Copy stuff from each side's send buffer to the other side's
249 # receive buffer.
250 for (read, write) in [(client_conn, server_conn),
251 (server_conn, client_conn)]:
252
253 # Give the side a chance to generate some more bytes, or
254 # succeed.
255 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400256 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400257 except WantReadError:
258 # It didn't succeed, so we'll hope it generated some
259 # output.
260 pass
261 else:
262 # It did succeed, so we'll stop now and let the caller deal
263 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400264 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400265
266 while True:
267 # Keep copying as long as there's more stuff there.
268 try:
269 dirty = read.bio_read(4096)
270 except WantReadError:
271 # Okay, nothing more waiting to be sent. Stop
272 # processing this send buffer.
273 break
274 else:
275 # Keep track of the fact that someone generated some
276 # output.
277 wrote = True
278 write.bio_write(dirty)
279
280
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400281
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400282class VersionTests(TestCase):
283 """
284 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900285 :py:obj:`OpenSSL.SSL.SSLeay_version` and
286 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400287 """
288 def test_OPENSSL_VERSION_NUMBER(self):
289 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900290 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400291 byte and the patch, fix, minor, and major versions in the
292 nibbles above that.
293 """
294 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
295
296
297 def test_SSLeay_version(self):
298 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900299 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400300 one of a number of version strings based on that indicator.
301 """
302 versions = {}
303 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
304 SSLEAY_PLATFORM, SSLEAY_DIR]:
305 version = SSLeay_version(t)
306 versions[version] = t
307 self.assertTrue(isinstance(version, bytes))
308 self.assertEqual(len(versions), 5)
309
310
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400311
312class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400313 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900314 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400315 """
316 def test_method(self):
317 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900318 :py:obj:`Context` can be instantiated with one of :py:obj:`SSLv2_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400319 :py:obj:`SSLv3_METHOD`, :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
320 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400321 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400322 methods = [
323 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
324 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400325 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400326
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400327
328 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
329 for meth in maybe:
330 try:
331 Context(meth)
332 except (Error, ValueError):
333 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
334 # don't. Difficult to say in advance.
335 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400336
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400337 self.assertRaises(TypeError, Context, "")
338 self.assertRaises(ValueError, Context, 10)
339
340
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500341 if not PY3:
342 def test_method_long(self):
343 """
344 On Python 2 :py:class:`Context` accepts values of type
345 :py:obj:`long` as well as :py:obj:`int`.
346 """
347 Context(long(TLSv1_METHOD))
348
349
350
Rick Deane15b1472009-07-09 15:53:42 -0500351 def test_type(self):
352 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900353 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400354 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500355 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400356 self.assertIdentical(Context, ContextType)
357 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500358
359
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400360 def test_use_privatekey(self):
361 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900362 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400363 """
364 key = PKey()
365 key.generate_key(TYPE_RSA, 128)
366 ctx = Context(TLSv1_METHOD)
367 ctx.use_privatekey(key)
368 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400369
370
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800371 def test_use_privatekey_file_missing(self):
372 """
373 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error`
374 when passed the name of a file which does not exist.
375 """
376 ctx = Context(TLSv1_METHOD)
377 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
378
379
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500380 if not PY3:
381 def test_use_privatekey_file_long(self):
382 """
383 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
384 filetype of type :py:obj:`long` as well as :py:obj:`int`.
385 """
386 pemfile = self.mktemp()
387
388 key = PKey()
389 key.generate_key(TYPE_RSA, 128)
390
391 with open(pemfile, "wt") as pem:
392 pem.write(
393 dump_privatekey(FILETYPE_PEM, key).decode("ascii"))
394
395 ctx = Context(TLSv1_METHOD)
396 ctx.use_privatekey_file(pemfile, long(FILETYPE_PEM))
397
398
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800399 def test_use_certificate_wrong_args(self):
400 """
401 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
402 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as an
403 argument.
404 """
405 ctx = Context(TLSv1_METHOD)
406 self.assertRaises(TypeError, ctx.use_certificate)
407 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
408 self.assertRaises(TypeError, ctx.use_certificate, X509(), "hello, world")
409
410
411 def test_use_certificate_uninitialized(self):
412 """
413 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
414 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
415 initialized (ie, which does not actually have any certificate data).
416 """
417 ctx = Context(TLSv1_METHOD)
418 self.assertRaises(Error, ctx.use_certificate, X509())
419
420
421 def test_use_certificate(self):
422 """
423 :py:obj:`Context.use_certificate` sets the certificate which will be
424 used to identify connections created using the context.
425 """
426 # TODO
427 # Hard to assert anything. But we could set a privatekey then ask
428 # OpenSSL if the cert and key agree using check_privatekey. Then as
429 # long as check_privatekey works right we're good...
430 ctx = Context(TLSv1_METHOD)
431 ctx.use_certificate(load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
432
433
434 def test_use_certificate_file_wrong_args(self):
435 """
436 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
437 called with zero arguments or more than two arguments, or if the first
438 argument is not a byte string or the second argumnent is not an integer.
439 """
440 ctx = Context(TLSv1_METHOD)
441 self.assertRaises(TypeError, ctx.use_certificate_file)
442 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile", object())
443 self.assertRaises(
444 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM, object())
445 self.assertRaises(
446 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
447 self.assertRaises(
448 TypeError, ctx.use_certificate_file, b"somefile", object())
449
450
451 def test_use_certificate_file_missing(self):
452 """
453 :py:obj:`Context.use_certificate_file` raises
454 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does not
455 exist.
456 """
457 ctx = Context(TLSv1_METHOD)
458 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
459
460
461 def test_use_certificate_file(self):
462 """
463 :py:obj:`Context.use_certificate` sets the certificate which will be
464 used to identify connections created using the context.
465 """
466 # TODO
467 # Hard to assert anything. But we could set a privatekey then ask
468 # OpenSSL if the cert and key agree using check_privatekey. Then as
469 # long as check_privatekey works right we're good...
470 pem_filename = self.mktemp()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500471 with open(pem_filename, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800472 pem_file.write(cleartextCertificatePEM)
473
474 ctx = Context(TLSv1_METHOD)
475 ctx.use_certificate_file(pem_filename)
476
477
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500478 if not PY3:
479 def test_use_certificate_file_long(self):
480 """
481 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
482 filetype of type :py:obj:`long` as well as :py:obj:`int`.
483 """
484 pem_filename = self.mktemp()
485 with open(pem_filename, "wb") as pem_file:
486 pem_file.write(cleartextCertificatePEM)
487
488 ctx = Context(TLSv1_METHOD)
489 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
490
491
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400492 def test_set_app_data_wrong_args(self):
493 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900494 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called with other than
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400495 one argument.
496 """
497 context = Context(TLSv1_METHOD)
498 self.assertRaises(TypeError, context.set_app_data)
499 self.assertRaises(TypeError, context.set_app_data, None, None)
500
501
502 def test_get_app_data_wrong_args(self):
503 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900504 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400505 arguments.
506 """
507 context = Context(TLSv1_METHOD)
508 self.assertRaises(TypeError, context.get_app_data, None)
509
510
511 def test_app_data(self):
512 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900513 :py:obj:`Context.set_app_data` stores an object for later retrieval using
514 :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400515 """
516 app_data = object()
517 context = Context(TLSv1_METHOD)
518 context.set_app_data(app_data)
519 self.assertIdentical(context.get_app_data(), app_data)
520
521
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400522 def test_set_options_wrong_args(self):
523 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900524 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with the wrong
525 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400526 """
527 context = Context(TLSv1_METHOD)
528 self.assertRaises(TypeError, context.set_options)
529 self.assertRaises(TypeError, context.set_options, None)
530 self.assertRaises(TypeError, context.set_options, 1, None)
531
532
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500533 def test_set_options(self):
534 """
535 :py:obj:`Context.set_options` returns the new options value.
536 """
537 context = Context(TLSv1_METHOD)
538 options = context.set_options(OP_NO_SSLv2)
539 self.assertTrue(OP_NO_SSLv2 & options)
540
541
542 if not PY3:
543 def test_set_options_long(self):
544 """
545 On Python 2 :py:obj:`Context.set_options` accepts values of type
546 :py:obj:`long` as well as :py:obj:`int`.
547 """
548 context = Context(TLSv1_METHOD)
549 options = context.set_options(long(OP_NO_SSLv2))
550 self.assertTrue(OP_NO_SSLv2 & options)
551
552
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300553 def test_set_mode_wrong_args(self):
554 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400555 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with the wrong
556 number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300557 """
558 context = Context(TLSv1_METHOD)
559 self.assertRaises(TypeError, context.set_mode)
560 self.assertRaises(TypeError, context.set_mode, None)
561 self.assertRaises(TypeError, context.set_mode, 1, None)
562
563
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400564 if MODE_RELEASE_BUFFERS is not None:
565 def test_set_mode(self):
566 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400567 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the newly
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400568 set mode.
569 """
570 context = Context(TLSv1_METHOD)
571 self.assertTrue(
572 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500573
574 if not PY3:
575 def test_set_mode_long(self):
576 """
577 On Python 2 :py:obj:`Context.set_mode` accepts values of type
578 :py:obj:`long` as well as :py:obj:`int`.
579 """
580 context = Context(TLSv1_METHOD)
581 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
582 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400583 else:
584 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
585
586
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400587 def test_set_timeout_wrong_args(self):
588 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900589 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with the wrong
590 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400591 """
592 context = Context(TLSv1_METHOD)
593 self.assertRaises(TypeError, context.set_timeout)
594 self.assertRaises(TypeError, context.set_timeout, None)
595 self.assertRaises(TypeError, context.set_timeout, 1, None)
596
597
598 def test_get_timeout_wrong_args(self):
599 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900600 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400601 """
602 context = Context(TLSv1_METHOD)
603 self.assertRaises(TypeError, context.get_timeout, None)
604
605
606 def test_timeout(self):
607 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900608 :py:obj:`Context.set_timeout` sets the session timeout for all connections
609 created using the context object. :py:obj:`Context.get_timeout` retrieves this
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400610 value.
611 """
612 context = Context(TLSv1_METHOD)
613 context.set_timeout(1234)
614 self.assertEquals(context.get_timeout(), 1234)
615
616
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500617 if not PY3:
618 def test_timeout_long(self):
619 """
620 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
621 `long` as well as int.
622 """
623 context = Context(TLSv1_METHOD)
624 context.set_timeout(long(1234))
625 self.assertEquals(context.get_timeout(), 1234)
626
627
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400628 def test_set_verify_depth_wrong_args(self):
629 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900630 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called with the wrong
631 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400632 """
633 context = Context(TLSv1_METHOD)
634 self.assertRaises(TypeError, context.set_verify_depth)
635 self.assertRaises(TypeError, context.set_verify_depth, None)
636 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
637
638
639 def test_get_verify_depth_wrong_args(self):
640 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900641 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400642 """
643 context = Context(TLSv1_METHOD)
644 self.assertRaises(TypeError, context.get_verify_depth, None)
645
646
647 def test_verify_depth(self):
648 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900649 :py:obj:`Context.set_verify_depth` sets the number of certificates in a chain
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400650 to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900651 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400652 """
653 context = Context(TLSv1_METHOD)
654 context.set_verify_depth(11)
655 self.assertEquals(context.get_verify_depth(), 11)
656
657
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500658 if not PY3:
659 def test_verify_depth_long(self):
660 """
661 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
662 type `long` as well as int.
663 """
664 context = Context(TLSv1_METHOD)
665 context.set_verify_depth(long(11))
666 self.assertEquals(context.get_verify_depth(), 11)
667
668
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400669 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400670 """
671 Write a new private key out to a new file, encrypted using the given
672 passphrase. Return the path to the new file.
673 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400674 key = PKey()
675 key.generate_key(TYPE_RSA, 128)
676 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400677 fObj = open(pemFile, 'w')
678 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
679 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400680 fObj.close()
681 return pemFile
682
683
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400684 def test_set_passwd_cb_wrong_args(self):
685 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900686 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called with the
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400687 wrong arguments or with a non-callable first argument.
688 """
689 context = Context(TLSv1_METHOD)
690 self.assertRaises(TypeError, context.set_passwd_cb)
691 self.assertRaises(TypeError, context.set_passwd_cb, None)
692 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
693
694
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400695 def test_set_passwd_cb(self):
696 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900697 :py:obj:`Context.set_passwd_cb` accepts a callable which will be invoked when
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400698 a private key is loaded from an encrypted PEM.
699 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400700 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400701 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400702 calledWith = []
703 def passphraseCallback(maxlen, verify, extra):
704 calledWith.append((maxlen, verify, extra))
705 return passphrase
706 context = Context(TLSv1_METHOD)
707 context.set_passwd_cb(passphraseCallback)
708 context.use_privatekey_file(pemFile)
709 self.assertTrue(len(calledWith), 1)
710 self.assertTrue(isinstance(calledWith[0][0], int))
711 self.assertTrue(isinstance(calledWith[0][1], int))
712 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400713
714
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400715 def test_passwd_callback_exception(self):
716 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900717 :py:obj:`Context.use_privatekey_file` propagates any exception raised by the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400718 passphrase callback.
719 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400720 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400721 def passphraseCallback(maxlen, verify, extra):
722 raise RuntimeError("Sorry, I am a fail.")
723
724 context = Context(TLSv1_METHOD)
725 context.set_passwd_cb(passphraseCallback)
726 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
727
728
729 def test_passwd_callback_false(self):
730 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900731 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400732 passphrase callback returns a false value.
733 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400734 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400735 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500736 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400737
738 context = Context(TLSv1_METHOD)
739 context.set_passwd_cb(passphraseCallback)
740 self.assertRaises(Error, context.use_privatekey_file, pemFile)
741
742
743 def test_passwd_callback_non_string(self):
744 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900745 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400746 passphrase callback returns a true non-string value.
747 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400748 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400749 def passphraseCallback(maxlen, verify, extra):
750 return 10
751
752 context = Context(TLSv1_METHOD)
753 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800754 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400755
756
757 def test_passwd_callback_too_long(self):
758 """
759 If the passphrase returned by the passphrase callback returns a string
760 longer than the indicated maximum length, it is truncated.
761 """
762 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400763 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400764 pemFile = self._write_encrypted_pem(passphrase)
765 def passphraseCallback(maxlen, verify, extra):
766 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400767 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400768
769 context = Context(TLSv1_METHOD)
770 context.set_passwd_cb(passphraseCallback)
771 # This shall succeed because the truncated result is the correct
772 # passphrase.
773 context.use_privatekey_file(pemFile)
774
775
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400776 def test_set_info_callback(self):
777 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900778 :py:obj:`Context.set_info_callback` accepts a callable which will be invoked
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400779 when certain information about an SSL connection is available.
780 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500781 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400782
783 clientSSL = Connection(Context(TLSv1_METHOD), client)
784 clientSSL.set_connect_state()
785
786 called = []
787 def info(conn, where, ret):
788 called.append((conn, where, ret))
789 context = Context(TLSv1_METHOD)
790 context.set_info_callback(info)
791 context.use_certificate(
792 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
793 context.use_privatekey(
794 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
795
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400796 serverSSL = Connection(context, server)
797 serverSSL.set_accept_state()
798
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500799 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400800
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500801 # The callback must always be called with a Connection instance as the
802 # first argument. It would probably be better to split this into
803 # separate tests for client and server side info callbacks so we could
804 # assert it is called with the right Connection instance. It would
805 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500806 notConnections = [
807 conn for (conn, where, ret) in called
808 if not isinstance(conn, Connection)]
809 self.assertEqual(
810 [], notConnections,
811 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400812
813
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400814 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400815 """
816 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400817 its :py:obj:`load_verify_locations` method with the given arguments.
818 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400819 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500820 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400821
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400822 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400823 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400824 # Require that the server certificate verify properly or the
825 # connection will fail.
826 clientContext.set_verify(
827 VERIFY_PEER,
828 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
829
830 clientSSL = Connection(clientContext, client)
831 clientSSL.set_connect_state()
832
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400833 serverContext = Context(TLSv1_METHOD)
834 serverContext.use_certificate(
835 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
836 serverContext.use_privatekey(
837 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
838
839 serverSSL = Connection(serverContext, server)
840 serverSSL.set_accept_state()
841
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400842 # Without load_verify_locations above, the handshake
843 # will fail:
844 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
845 # 'certificate verify failed')]
846 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400847
848 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400849 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400850
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500851
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400852 def test_load_verify_file(self):
853 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900854 :py:obj:`Context.load_verify_locations` accepts a file name and uses the
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400855 certificates within for verification purposes.
856 """
857 cafile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400858 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400859 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400860 fObj.close()
861
862 self._load_verify_locations_test(cafile)
863
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400864
865 def test_load_verify_invalid_file(self):
866 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900867 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when passed a
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400868 non-existent cafile.
869 """
870 clientContext = Context(TLSv1_METHOD)
871 self.assertRaises(
872 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400873
874
875 def test_load_verify_directory(self):
876 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900877 :py:obj:`Context.load_verify_locations` accepts a directory name and uses
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400878 the certificates within for verification purposes.
879 """
880 capath = self.mktemp()
881 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400882 # Hash values computed manually with c_rehash to avoid depending on
883 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
884 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500885 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400886 cafile = join(capath, name)
887 fObj = open(cafile, 'w')
888 fObj.write(cleartextCertificatePEM.decode('ascii'))
889 fObj.close()
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400890
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400891 self._load_verify_locations_test(None, capath)
892
893
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400894 def test_load_verify_locations_wrong_args(self):
895 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900896 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if called with
897 the wrong number of arguments or with non-:py:obj:`str` arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400898 """
899 context = Context(TLSv1_METHOD)
900 self.assertRaises(TypeError, context.load_verify_locations)
901 self.assertRaises(TypeError, context.load_verify_locations, object())
902 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
903 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
904
905
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400906 if platform == "win32":
907 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400908 "See LP#404343 and LP#404344."
909 else:
910 def test_set_default_verify_paths(self):
911 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900912 :py:obj:`Context.set_default_verify_paths` causes the platform-specific CA
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400913 certificate locations to be used for verification purposes.
914 """
915 # Testing this requires a server with a certificate signed by one of
916 # the CAs in the platform CA location. Getting one of those costs
917 # money. Fortunately (or unfortunately, depending on your
918 # perspective), it's easy to think of a public server on the
919 # internet which has such a certificate. Connecting to the network
920 # in a unit test is bad, but it's the only way I can think of to
921 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400922
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400923 # Arg, verisign.com doesn't speak TLSv1
924 context = Context(SSLv3_METHOD)
925 context.set_default_verify_paths()
926 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +0200927 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400928 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400929
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400930 client = socket()
931 client.connect(('verisign.com', 443))
932 clientSSL = Connection(context, client)
933 clientSSL.set_connect_state()
934 clientSSL.do_handshake()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500935 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400936 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400937
938
939 def test_set_default_verify_paths_signature(self):
940 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900941 :py:obj:`Context.set_default_verify_paths` takes no arguments and raises
942 :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400943 """
944 context = Context(TLSv1_METHOD)
945 self.assertRaises(TypeError, context.set_default_verify_paths, None)
946 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
947 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500948
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400949
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500950 def test_add_extra_chain_cert_invalid_cert(self):
951 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900952 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if called with
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500953 other than one argument or if called with an object which is not an
Jonathan Ballet648875f2011-07-16 14:14:58 +0900954 instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500955 """
956 context = Context(TLSv1_METHOD)
957 self.assertRaises(TypeError, context.add_extra_chain_cert)
958 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
959 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
960
961
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400962 def _handshake_test(self, serverContext, clientContext):
963 """
964 Verify that a client and server created with the given contexts can
965 successfully handshake and communicate.
966 """
967 serverSocket, clientSocket = socket_pair()
968
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400969 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400970 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400971
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400972 client = Connection(clientContext, clientSocket)
973 client.set_connect_state()
974
975 # Make them talk to each other.
976 # self._interactInMemory(client, server)
977 for i in range(3):
978 for s in [client, server]:
979 try:
980 s.do_handshake()
981 except WantReadError:
982 pass
983
984
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800985 def test_set_verify_callback_exception(self):
986 """
987 If the verify callback passed to :py:obj:`Context.set_verify` raises an
988 exception, verification fails and the exception is propagated to the
989 caller of :py:obj:`Connection.do_handshake`.
990 """
991 serverContext = Context(TLSv1_METHOD)
992 serverContext.use_privatekey(
993 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
994 serverContext.use_certificate(
995 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
996
997 clientContext = Context(TLSv1_METHOD)
998 def verify_callback(*args):
999 raise Exception("silly verify failure")
1000 clientContext.set_verify(VERIFY_PEER, verify_callback)
1001
1002 exc = self.assertRaises(
1003 Exception, self._handshake_test, serverContext, clientContext)
1004 self.assertEqual("silly verify failure", str(exc))
1005
1006
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001007 def test_add_extra_chain_cert(self):
1008 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001009 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509` instance to add to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001010 the certificate chain.
1011
Jonathan Ballet648875f2011-07-16 14:14:58 +09001012 See :py:obj:`_create_certificate_chain` for the details of the certificate
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001013 chain tested.
1014
1015 The chain is tested by starting a server with scert and connecting
1016 to it with a client which trusts cacert and requires verification to
1017 succeed.
1018 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001019 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001020 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1021
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001022 # Dump the CA certificate to a file because that's the only way to load
1023 # it as a trusted CA in the client context.
1024 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001025 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001026 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001027 fObj.close()
1028
1029 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001030 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001031 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001032 fObj.close()
1033
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001034 # Create the server context
1035 serverContext = Context(TLSv1_METHOD)
1036 serverContext.use_privatekey(skey)
1037 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001038 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001039 serverContext.add_extra_chain_cert(icert)
1040
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001041 # Create the client
1042 clientContext = Context(TLSv1_METHOD)
1043 clientContext.set_verify(
1044 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001045 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001046
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001047 # Try it out.
1048 self._handshake_test(serverContext, clientContext)
1049
1050
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001051 def test_use_certificate_chain_file(self):
1052 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001053 :py:obj:`Context.use_certificate_chain_file` reads a certificate chain from
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001054 the specified file.
1055
1056 The chain is tested by starting a server with scert and connecting
1057 to it with a client which trusts cacert and requires verification to
1058 succeed.
1059 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001060 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001061 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1062
1063 # Write out the chain file.
1064 chainFile = self.mktemp()
Jean-Paul Calderoned8607982014-01-18 10:30:55 -05001065 fObj = open(chainFile, 'wb')
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001066 # Most specific to least general.
Jean-Paul Calderoned8607982014-01-18 10:30:55 -05001067 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1068 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1069 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001070 fObj.close()
1071
1072 serverContext = Context(TLSv1_METHOD)
1073 serverContext.use_certificate_chain_file(chainFile)
1074 serverContext.use_privatekey(skey)
1075
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001076 fObj = open('ca.pem', 'w')
1077 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001078 fObj.close()
1079
1080 clientContext = Context(TLSv1_METHOD)
1081 clientContext.set_verify(
1082 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001083 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001084
1085 self._handshake_test(serverContext, clientContext)
1086
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001087
1088 def test_use_certificate_chain_file_wrong_args(self):
1089 """
1090 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1091 if passed zero or more than one argument or when passed a non-byte
1092 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error` when
1093 passed a bad chain file name (for example, the name of a file which does
1094 not exist).
1095 """
1096 context = Context(TLSv1_METHOD)
1097 self.assertRaises(TypeError, context.use_certificate_chain_file)
1098 self.assertRaises(TypeError, context.use_certificate_chain_file, object())
1099 self.assertRaises(TypeError, context.use_certificate_chain_file, b"foo", object())
1100
1101 self.assertRaises(Error, context.use_certificate_chain_file, self.mktemp())
1102
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001103 # XXX load_client_ca
1104 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001105
1106 def test_get_verify_mode_wrong_args(self):
1107 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001108 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001109 arguments.
1110 """
1111 context = Context(TLSv1_METHOD)
1112 self.assertRaises(TypeError, context.get_verify_mode, None)
1113
1114
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001115 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001116 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001117 :py:obj:`Context.get_verify_mode` returns the verify mode flags previously
1118 passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001119 """
1120 context = Context(TLSv1_METHOD)
1121 self.assertEquals(context.get_verify_mode(), 0)
1122 context.set_verify(
1123 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1124 self.assertEquals(
1125 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1126
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001127
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001128 if not PY3:
1129 def test_set_verify_mode_long(self):
1130 """
1131 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1132 type :py:obj:`long` as well as :py:obj:`int`.
1133 """
1134 context = Context(TLSv1_METHOD)
1135 self.assertEquals(context.get_verify_mode(), 0)
1136 context.set_verify(
1137 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None)
1138 self.assertEquals(
1139 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1140
1141
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001142 def test_load_tmp_dh_wrong_args(self):
1143 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001144 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
1145 number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001146 """
1147 context = Context(TLSv1_METHOD)
1148 self.assertRaises(TypeError, context.load_tmp_dh)
1149 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1150 self.assertRaises(TypeError, context.load_tmp_dh, object())
1151
1152
1153 def test_load_tmp_dh_missing_file(self):
1154 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001155 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the specified file
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001156 does not exist.
1157 """
1158 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001159 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001160
1161
1162 def test_load_tmp_dh(self):
1163 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001164 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001165 specified file.
1166 """
1167 context = Context(TLSv1_METHOD)
1168 dhfilename = self.mktemp()
1169 dhfile = open(dhfilename, "w")
1170 dhfile.write(dhparam)
1171 dhfile.close()
1172 context.load_tmp_dh(dhfilename)
1173 # XXX What should I assert here? -exarkun
1174
1175
Alex Gaynor807853c2014-01-17 13:03:27 -06001176 if _Cryptography_HAS_EC:
Alex Gaynor12dc0842014-01-17 12:51:31 -06001177 def test_set_tmp_ecdh_by_curve_name(self):
1178 """
1179 :py:obj:`Context.set_tmp_ecdh_by_curve_name` sets the Eliptical
1180 Curve for Diffie-Hellman by the named curve.
1181 """
1182 context = Context(TLSv1_METHOD)
1183 context.set_tmp_ecdh_by_curve_name(NID_X9_62_prime256v1)
1184 # XXX What should I assert here? -alex
1185
1186
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001187 def test_set_cipher_list_bytes(self):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001188 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001189 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
1190 ciphers which connections created with the context object will be able
1191 to choose from.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001192 """
1193 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001194 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001195 conn = Connection(context, None)
1196 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001197
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001198
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001199 def test_set_cipher_list_text(self):
1200 """
1201 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
1202 the ciphers which connections created with the context object will be
1203 able to choose from.
1204 """
1205 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -05001206 context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001207 conn = Connection(context, None)
1208 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
1209
1210
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001211 def test_set_cipher_list_wrong_args(self):
1212 """
Jean-Paul Calderone17044832014-01-18 10:20:11 -05001213 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
1214 passed zero arguments or more than one argument or when passed a
1215 non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001216 passed an incorrect cipher list string.
1217 """
1218 context = Context(TLSv1_METHOD)
1219 self.assertRaises(TypeError, context.set_cipher_list)
1220 self.assertRaises(TypeError, context.set_cipher_list, object())
1221 self.assertRaises(TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object())
1222
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001223 self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001224
1225
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001226 def test_set_session_cache_mode_wrong_args(self):
1227 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001228 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1229 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001230 """
1231 context = Context(TLSv1_METHOD)
1232 self.assertRaises(TypeError, context.set_session_cache_mode)
1233 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1234
1235
1236 def test_get_session_cache_mode_wrong_args(self):
1237 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001238 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1239 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001240 """
1241 context = Context(TLSv1_METHOD)
1242 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1243
1244
1245 def test_session_cache_mode(self):
1246 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001247 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1248 cached. The setting can be retrieved via
1249 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001250 """
1251 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001252 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001253 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1254 self.assertEqual(SESS_CACHE_OFF, off)
1255 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1256
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001257 if not PY3:
1258 def test_session_cache_mode_long(self):
1259 """
1260 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1261 of type :py:obj:`long` as well as :py:obj:`int`.
1262 """
1263 context = Context(TLSv1_METHOD)
1264 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1265 self.assertEqual(
1266 SESS_CACHE_BOTH, context.get_session_cache_mode())
1267
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001268
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001269 def test_get_cert_store(self):
1270 """
1271 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store` instance.
1272 """
1273 context = Context(TLSv1_METHOD)
1274 store = context.get_cert_store()
1275 self.assertIsInstance(store, X509Store)
1276
1277
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001278
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001279class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1280 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001281 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
1282 :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001283 """
1284 def test_wrong_args(self):
1285 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001286 :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001287 with other than one argument.
1288 """
1289 context = Context(TLSv1_METHOD)
1290 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1291 self.assertRaises(
1292 TypeError, context.set_tlsext_servername_callback, 1, 2)
1293
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001294
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001295 def test_old_callback_forgotten(self):
1296 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001297 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001298 callback, the one it replaces is dereferenced.
1299 """
1300 def callback(connection):
1301 pass
1302
1303 def replacement(connection):
1304 pass
1305
1306 context = Context(TLSv1_METHOD)
1307 context.set_tlsext_servername_callback(callback)
1308
1309 tracker = ref(callback)
1310 del callback
1311
1312 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001313
1314 # One run of the garbage collector happens to work on CPython. PyPy
1315 # doesn't collect the underlying object until a second run for whatever
1316 # reason. That's fine, it still demonstrates our code has properly
1317 # dropped the reference.
1318 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001319 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001320
1321 callback = tracker()
1322 if callback is not None:
1323 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001324 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001325 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001326
1327
1328 def test_no_servername(self):
1329 """
1330 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001331 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
1332 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001333 """
1334 args = []
1335 def servername(conn):
1336 args.append((conn, conn.get_servername()))
1337 context = Context(TLSv1_METHOD)
1338 context.set_tlsext_servername_callback(servername)
1339
1340 # Lose our reference to it. The Context is responsible for keeping it
1341 # alive now.
1342 del servername
1343 collect()
1344
1345 # Necessary to actually accept the connection
1346 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1347 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1348
1349 # Do a little connection to trigger the logic
1350 server = Connection(context, None)
1351 server.set_accept_state()
1352
1353 client = Connection(Context(TLSv1_METHOD), None)
1354 client.set_connect_state()
1355
1356 self._interactInMemory(server, client)
1357
1358 self.assertEqual([(server, None)], args)
1359
1360
1361 def test_servername(self):
1362 """
1363 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +09001364 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
1365 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001366 """
1367 args = []
1368 def servername(conn):
1369 args.append((conn, conn.get_servername()))
1370 context = Context(TLSv1_METHOD)
1371 context.set_tlsext_servername_callback(servername)
1372
1373 # Necessary to actually accept the connection
1374 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1375 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1376
1377 # Do a little connection to trigger the logic
1378 server = Connection(context, None)
1379 server.set_accept_state()
1380
1381 client = Connection(Context(TLSv1_METHOD), None)
1382 client.set_connect_state()
1383 client.set_tlsext_host_name(b("foo1.example.com"))
1384
1385 self._interactInMemory(server, client)
1386
1387 self.assertEqual([(server, b("foo1.example.com"))], args)
1388
1389
1390
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001391class SessionTests(TestCase):
1392 """
1393 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1394 """
1395 def test_construction(self):
1396 """
1397 :py:class:`Session` can be constructed with no arguments, creating a new
1398 instance of that type.
1399 """
1400 new_session = Session()
1401 self.assertTrue(isinstance(new_session, Session))
1402
1403
1404 def test_construction_wrong_args(self):
1405 """
1406 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
1407 is raised.
1408 """
1409 self.assertRaises(TypeError, Session, 123)
1410 self.assertRaises(TypeError, Session, "hello")
1411 self.assertRaises(TypeError, Session, object())
1412
1413
1414
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001415class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05001416 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001417 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001418 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001419 # XXX get_peer_certificate -> None
1420 # XXX sock_shutdown
1421 # XXX master_key -> TypeError
1422 # XXX server_random -> TypeError
1423 # XXX state_string
1424 # XXX connect -> TypeError
1425 # XXX connect_ex -> TypeError
1426 # XXX set_connect_state -> TypeError
1427 # XXX set_accept_state -> TypeError
1428 # XXX renegotiate_pending
1429 # XXX do_handshake -> TypeError
1430 # XXX bio_read -> TypeError
1431 # XXX recv -> TypeError
1432 # XXX send -> TypeError
1433 # XXX bio_write -> TypeError
1434
Rick Deane15b1472009-07-09 15:53:42 -05001435 def test_type(self):
1436 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001437 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001438 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05001439 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001440 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05001441 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001442 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05001443
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001444
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001445 def test_get_context(self):
1446 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001447 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
1448 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001449 """
1450 context = Context(TLSv1_METHOD)
1451 connection = Connection(context, None)
1452 self.assertIdentical(connection.get_context(), context)
1453
1454
1455 def test_get_context_wrong_args(self):
1456 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001457 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001458 arguments.
1459 """
1460 connection = Connection(Context(TLSv1_METHOD), None)
1461 self.assertRaises(TypeError, connection.get_context, None)
1462
1463
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001464 def test_set_context_wrong_args(self):
1465 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001466 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
1467 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001468 than 1.
1469 """
1470 ctx = Context(TLSv1_METHOD)
1471 connection = Connection(ctx, None)
1472 self.assertRaises(TypeError, connection.set_context)
1473 self.assertRaises(TypeError, connection.set_context, object())
1474 self.assertRaises(TypeError, connection.set_context, "hello")
1475 self.assertRaises(TypeError, connection.set_context, 1)
1476 self.assertRaises(TypeError, connection.set_context, 1, 2)
1477 self.assertRaises(
1478 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
1479 self.assertIdentical(ctx, connection.get_context())
1480
1481
1482 def test_set_context(self):
1483 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001484 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001485 for the connection.
1486 """
1487 original = Context(SSLv23_METHOD)
1488 replacement = Context(TLSv1_METHOD)
1489 connection = Connection(original, None)
1490 connection.set_context(replacement)
1491 self.assertIdentical(replacement, connection.get_context())
1492 # Lose our references to the contexts, just in case the Connection isn't
1493 # properly managing its own contributions to their reference counts.
1494 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001495 collect()
1496
1497
1498 def test_set_tlsext_host_name_wrong_args(self):
1499 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001500 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001501 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09001502 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001503 """
1504 conn = Connection(Context(TLSv1_METHOD), None)
1505 self.assertRaises(TypeError, conn.set_tlsext_host_name)
1506 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
1507 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
1508 self.assertRaises(
1509 TypeError, conn.set_tlsext_host_name, b("with\0null"))
1510
1511 if version_info >= (3,):
1512 # On Python 3.x, don't accidentally implicitly convert from text.
1513 self.assertRaises(
1514 TypeError,
1515 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001516
1517
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001518 def test_get_servername_wrong_args(self):
1519 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001520 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001521 arguments.
1522 """
1523 connection = Connection(Context(TLSv1_METHOD), None)
1524 self.assertRaises(TypeError, connection.get_servername, object())
1525 self.assertRaises(TypeError, connection.get_servername, 1)
1526 self.assertRaises(TypeError, connection.get_servername, "hello")
1527
1528
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001529 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001530 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001531 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001532 immediate read.
1533 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001534 connection = Connection(Context(TLSv1_METHOD), None)
1535 self.assertEquals(connection.pending(), 0)
1536
1537
1538 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001539 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001540 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001541 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001542 connection = Connection(Context(TLSv1_METHOD), None)
1543 self.assertRaises(TypeError, connection.pending, None)
1544
1545
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001546 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001547 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001548 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001549 argument or with the wrong number of arguments.
1550 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001551 connection = Connection(Context(TLSv1_METHOD), socket())
1552 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001553 self.assertRaises(TypeError, connection.connect)
1554 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001555
1556
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001557 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001558 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001559 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001560 connect method raises it.
1561 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001562 client = socket()
1563 context = Context(TLSv1_METHOD)
1564 clientSSL = Connection(context, client)
1565 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04001566 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001567
1568
1569 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001570 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001571 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001572 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001573 port = socket()
1574 port.bind(('', 0))
1575 port.listen(3)
1576
1577 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001578 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
1579 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001580
1581
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001582 if platform == "darwin":
1583 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
1584 else:
1585 def test_connect_ex(self):
1586 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001587 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001588 errno instead of raising an exception.
1589 """
1590 port = socket()
1591 port.bind(('', 0))
1592 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001593
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001594 clientSSL = Connection(Context(TLSv1_METHOD), socket())
1595 clientSSL.setblocking(False)
1596 result = clientSSL.connect_ex(port.getsockname())
1597 expected = (EINPROGRESS, EWOULDBLOCK)
1598 self.assertTrue(
1599 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001600
1601
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001602 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001603 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001604 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001605 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001606 connection = Connection(Context(TLSv1_METHOD), socket())
1607 self.assertRaises(TypeError, connection.accept, None)
1608
1609
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001610 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001611 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001612 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
1613 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001614 connection originated from.
1615 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001616 ctx = Context(TLSv1_METHOD)
1617 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1618 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001619 port = socket()
1620 portSSL = Connection(ctx, port)
1621 portSSL.bind(('', 0))
1622 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001623
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001624 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001625
1626 # Calling portSSL.getsockname() here to get the server IP address sounds
1627 # great, but frequently fails on Windows.
1628 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001629
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001630 serverSSL, address = portSSL.accept()
1631
1632 self.assertTrue(isinstance(serverSSL, Connection))
1633 self.assertIdentical(serverSSL.get_context(), ctx)
1634 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001635
1636
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001637 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001638 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001639 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001640 number of arguments or with arguments other than integers.
1641 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001642 connection = Connection(Context(TLSv1_METHOD), None)
1643 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04001644 self.assertRaises(TypeError, connection.get_shutdown, None)
1645 self.assertRaises(TypeError, connection.set_shutdown)
1646 self.assertRaises(TypeError, connection.set_shutdown, None)
1647 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001648
1649
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001650 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001651 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001652 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001653 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001654 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001655 self.assertFalse(server.shutdown())
1656 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001657 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001658 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
1659 client.shutdown()
1660 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
1661 self.assertRaises(ZeroReturnError, server.recv, 1024)
1662 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001663
1664
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001665 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001666 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001667 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001668 process.
1669 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001670 connection = Connection(Context(TLSv1_METHOD), socket())
1671 connection.set_shutdown(RECEIVED_SHUTDOWN)
1672 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1673
1674
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05001675 if not PY3:
1676 def test_set_shutdown_long(self):
1677 """
1678 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
1679 of type :py:obj:`long` as well as :py:obj:`int`.
1680 """
1681 connection = Connection(Context(TLSv1_METHOD), socket())
1682 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
1683 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1684
1685
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001686 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001687 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001688 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
1689 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001690 with any arguments.
1691 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001692 conn = Connection(Context(TLSv1_METHOD), None)
1693 self.assertRaises(TypeError, conn.get_app_data, None)
1694 self.assertRaises(TypeError, conn.set_app_data)
1695 self.assertRaises(TypeError, conn.set_app_data, None, None)
1696
1697
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001698 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001699 """
1700 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001701 :py:obj:`Connection.set_app_data` and later retrieved with
1702 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001703 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001704 conn = Connection(Context(TLSv1_METHOD), None)
1705 app_data = object()
1706 conn.set_app_data(app_data)
1707 self.assertIdentical(conn.get_app_data(), app_data)
1708
1709
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001710 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001711 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001712 :py:obj:`Connection.makefile` is not implemented and calling that method raises
1713 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001714 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001715 conn = Connection(Context(TLSv1_METHOD), None)
1716 self.assertRaises(NotImplementedError, conn.makefile)
1717
1718
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001719 def test_get_peer_cert_chain_wrong_args(self):
1720 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001721 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001722 arguments.
1723 """
1724 conn = Connection(Context(TLSv1_METHOD), None)
1725 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
1726 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
1727 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
1728 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
1729
1730
1731 def test_get_peer_cert_chain(self):
1732 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001733 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001734 the connected server returned for the certification verification.
1735 """
1736 chain = _create_certificate_chain()
1737 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1738
1739 serverContext = Context(TLSv1_METHOD)
1740 serverContext.use_privatekey(skey)
1741 serverContext.use_certificate(scert)
1742 serverContext.add_extra_chain_cert(icert)
1743 serverContext.add_extra_chain_cert(cacert)
1744 server = Connection(serverContext, None)
1745 server.set_accept_state()
1746
1747 # Create the client
1748 clientContext = Context(TLSv1_METHOD)
1749 clientContext.set_verify(VERIFY_NONE, verify_cb)
1750 client = Connection(clientContext, None)
1751 client.set_connect_state()
1752
1753 self._interactInMemory(client, server)
1754
1755 chain = client.get_peer_cert_chain()
1756 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001757 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001758 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001759 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001760 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001761 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001762 "Authority Certificate", chain[2].get_subject().CN)
1763
1764
1765 def test_get_peer_cert_chain_none(self):
1766 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001767 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001768 certificate chain.
1769 """
1770 ctx = Context(TLSv1_METHOD)
1771 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1772 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1773 server = Connection(ctx, None)
1774 server.set_accept_state()
1775 client = Connection(Context(TLSv1_METHOD), None)
1776 client.set_connect_state()
1777 self._interactInMemory(client, server)
1778 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001779
1780
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001781 def test_get_session_wrong_args(self):
1782 """
1783 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
1784 with any arguments.
1785 """
1786 ctx = Context(TLSv1_METHOD)
1787 server = Connection(ctx, None)
1788 self.assertRaises(TypeError, server.get_session, 123)
1789 self.assertRaises(TypeError, server.get_session, "hello")
1790 self.assertRaises(TypeError, server.get_session, object())
1791
1792
1793 def test_get_session_unconnected(self):
1794 """
1795 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
1796 an object which has not been connected.
1797 """
1798 ctx = Context(TLSv1_METHOD)
1799 server = Connection(ctx, None)
1800 session = server.get_session()
1801 self.assertIdentical(None, session)
1802
1803
1804 def test_server_get_session(self):
1805 """
1806 On the server side of a connection, :py:obj:`Connection.get_session`
1807 returns a :py:class:`Session` instance representing the SSL session for
1808 that connection.
1809 """
1810 server, client = self._loopback()
1811 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001812 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001813
1814
1815 def test_client_get_session(self):
1816 """
1817 On the client side of a connection, :py:obj:`Connection.get_session`
1818 returns a :py:class:`Session` instance representing the SSL session for
1819 that connection.
1820 """
1821 server, client = self._loopback()
1822 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001823 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001824
1825
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05001826 def test_set_session_wrong_args(self):
1827 """
1828 If called with an object that is not an instance of :py:class:`Session`,
1829 or with other than one argument, :py:obj:`Connection.set_session` raises
1830 :py:obj:`TypeError`.
1831 """
1832 ctx = Context(TLSv1_METHOD)
1833 connection = Connection(ctx, None)
1834 self.assertRaises(TypeError, connection.set_session)
1835 self.assertRaises(TypeError, connection.set_session, 123)
1836 self.assertRaises(TypeError, connection.set_session, "hello")
1837 self.assertRaises(TypeError, connection.set_session, object())
1838 self.assertRaises(
1839 TypeError, connection.set_session, Session(), Session())
1840
1841
1842 def test_client_set_session(self):
1843 """
1844 :py:obj:`Connection.set_session`, when used prior to a connection being
1845 established, accepts a :py:class:`Session` instance and causes an
1846 attempt to re-use the session it represents when the SSL handshake is
1847 performed.
1848 """
1849 key = load_privatekey(FILETYPE_PEM, server_key_pem)
1850 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
1851 ctx = Context(TLSv1_METHOD)
1852 ctx.use_privatekey(key)
1853 ctx.use_certificate(cert)
1854 ctx.set_session_id("unity-test")
1855
1856 def makeServer(socket):
1857 server = Connection(ctx, socket)
1858 server.set_accept_state()
1859 return server
1860
1861 originalServer, originalClient = self._loopback(
1862 serverFactory=makeServer)
1863 originalSession = originalClient.get_session()
1864
1865 def makeClient(socket):
1866 client = self._loopbackClientFactory(socket)
1867 client.set_session(originalSession)
1868 return client
1869 resumedServer, resumedClient = self._loopback(
1870 serverFactory=makeServer,
1871 clientFactory=makeClient)
1872
1873 # This is a proxy: in general, we have no access to any unique
1874 # identifier for the session (new enough versions of OpenSSL expose a
1875 # hash which could be usable, but "new enough" is very, very new).
1876 # Instead, exploit the fact that the master key is re-used if the
1877 # session is re-used. As long as the master key for the two connections
1878 # is the same, the session was re-used!
1879 self.assertEqual(
1880 originalServer.master_key(), resumedServer.master_key())
1881
1882
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05001883 def test_set_session_wrong_method(self):
1884 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05001885 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
1886 instance associated with a context using a different SSL method than the
1887 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
1888 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05001889 """
1890 key = load_privatekey(FILETYPE_PEM, server_key_pem)
1891 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
1892 ctx = Context(TLSv1_METHOD)
1893 ctx.use_privatekey(key)
1894 ctx.use_certificate(cert)
1895 ctx.set_session_id("unity-test")
1896
1897 def makeServer(socket):
1898 server = Connection(ctx, socket)
1899 server.set_accept_state()
1900 return server
1901
1902 originalServer, originalClient = self._loopback(
1903 serverFactory=makeServer)
1904 originalSession = originalClient.get_session()
1905
1906 def makeClient(socket):
1907 # Intentionally use a different, incompatible method here.
1908 client = Connection(Context(SSLv3_METHOD), socket)
1909 client.set_connect_state()
1910 client.set_session(originalSession)
1911 return client
1912
1913 self.assertRaises(
1914 Error,
1915 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
1916
1917
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07001918 def test_wantWriteError(self):
1919 """
1920 :py:obj:`Connection` methods which generate output raise
1921 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
1922 fail indicating a should-write state.
1923 """
1924 client_socket, server_socket = socket_pair()
1925 # Fill up the client's send buffer so Connection won't be able to write
1926 # anything.
Jean-Paul Calderone7d7c9c22014-02-18 16:38:26 -05001927 msg = b"x" * 512
Jean-Paul Calderone22c28b42014-02-18 16:40:34 -05001928 for i in range(2048):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07001929 try:
1930 client_socket.send(msg)
1931 except error as e:
1932 if e.errno == EWOULDBLOCK:
1933 break
1934 raise
1935 else:
1936 self.fail(
1937 "Failed to fill socket buffer, cannot test BIO want write")
1938
1939 ctx = Context(TLSv1_METHOD)
1940 conn = Connection(ctx, client_socket)
1941 # Client's speak first, so make it an SSL client
1942 conn.set_connect_state()
1943 self.assertRaises(WantWriteError, conn.do_handshake)
1944
1945 # XXX want_read
1946
1947
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001948
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001949class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001950 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001951 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001952 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04001953 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001954 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001955 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001956 arguments.
1957 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001958 connection = Connection(Context(TLSv1_METHOD), None)
1959 self.assertRaises(TypeError, connection.get_cipher_list, None)
1960
1961
1962 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001963 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001964 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
1965 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001966 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001967 connection = Connection(Context(TLSv1_METHOD), None)
1968 ciphers = connection.get_cipher_list()
1969 self.assertTrue(isinstance(ciphers, list))
1970 for cipher in ciphers:
1971 self.assertTrue(isinstance(cipher, str))
1972
1973
1974
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001975class ConnectionSendTests(TestCase, _LoopbackMixin):
1976 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001977 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001978 """
1979 def test_wrong_args(self):
1980 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001981 When called with arguments other than string argument for its first
1982 parameter or more than two arguments, :py:obj:`Connection.send` raises
1983 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001984 """
1985 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05001986 self.assertRaises(TypeError, connection.send)
1987 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001988 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001989
1990
1991 def test_short_bytes(self):
1992 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001993 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001994 and returns the number of bytes sent.
1995 """
1996 server, client = self._loopback()
1997 count = server.send(b('xy'))
1998 self.assertEquals(count, 2)
1999 self.assertEquals(client.recv(2), b('xy'))
2000
2001 try:
2002 memoryview
2003 except NameError:
2004 "cannot test sending memoryview without memoryview"
2005 else:
2006 def test_short_memoryview(self):
2007 """
2008 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002009 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002010 bytes sent.
2011 """
2012 server, client = self._loopback()
2013 count = server.send(memoryview(b('xy')))
2014 self.assertEquals(count, 2)
2015 self.assertEquals(client.recv(2), b('xy'))
2016
2017
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002018
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002019class ConnectionSendallTests(TestCase, _LoopbackMixin):
2020 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002021 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002022 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002023 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002024 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002025 When called with arguments other than a string argument for its first
2026 parameter or with more than two arguments, :py:obj:`Connection.sendall`
2027 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002028 """
2029 connection = Connection(Context(TLSv1_METHOD), None)
2030 self.assertRaises(TypeError, connection.sendall)
2031 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002032 self.assertRaises(
2033 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002034
2035
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002036 def test_short(self):
2037 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002038 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002039 it.
2040 """
2041 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04002042 server.sendall(b('x'))
2043 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002044
2045
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002046 try:
2047 memoryview
2048 except NameError:
2049 "cannot test sending memoryview without memoryview"
2050 else:
2051 def test_short_memoryview(self):
2052 """
2053 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002054 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002055 """
2056 server, client = self._loopback()
2057 server.sendall(memoryview(b('x')))
2058 self.assertEquals(client.recv(1), b('x'))
2059
2060
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002061 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002062 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002063 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002064 it even if this requires multiple calls of an underlying write function.
2065 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002066 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04002067 # Should be enough, underlying SSL_write should only do 16k at a time.
2068 # On Windows, after 32k of bytes the write will block (forever - because
2069 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04002070 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002071 server.sendall(message)
2072 accum = []
2073 received = 0
2074 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04002075 data = client.recv(1024)
2076 accum.append(data)
2077 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04002078 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002079
2080
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002081 def test_closed(self):
2082 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002083 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002084 write error from the low level write call.
2085 """
2086 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04002087 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002088 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02002089 if platform == "win32":
2090 self.assertEqual(exc.args[0], ESHUTDOWN)
2091 else:
2092 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002093
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002094
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002095
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002096class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
2097 """
2098 Tests for SSL renegotiation APIs.
2099 """
2100 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002101 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002102 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002103 arguments.
2104 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002105 connection = Connection(Context(TLSv1_METHOD), None)
2106 self.assertRaises(TypeError, connection.renegotiate, None)
2107
2108
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002109 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002110 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002111 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002112 any arguments.
2113 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002114 connection = Connection(Context(TLSv1_METHOD), None)
2115 self.assertRaises(TypeError, connection.total_renegotiations, None)
2116
2117
2118 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002119 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002120 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002121 renegotiations have happened.
2122 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002123 connection = Connection(Context(TLSv1_METHOD), None)
2124 self.assertEquals(connection.total_renegotiations(), 0)
2125
2126
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002127# def test_renegotiate(self):
2128# """
2129# """
2130# server, client = self._loopback()
2131
2132# server.send("hello world")
2133# self.assertEquals(client.recv(len("hello world")), "hello world")
2134
2135# self.assertEquals(server.total_renegotiations(), 0)
2136# self.assertTrue(server.renegotiate())
2137
2138# server.setblocking(False)
2139# client.setblocking(False)
2140# while server.renegotiate_pending():
2141# client.do_handshake()
2142# server.do_handshake()
2143
2144# self.assertEquals(server.total_renegotiations(), 1)
2145
2146
2147
2148
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002149class ErrorTests(TestCase):
2150 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002151 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002152 """
2153 def test_type(self):
2154 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002155 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002156 """
2157 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05002158 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05002159
2160
2161
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002162class ConstantsTests(TestCase):
2163 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002164 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002165
2166 These are values defined by OpenSSL intended only to be used as flags to
2167 OpenSSL APIs. The only assertions it seems can be made about them is
2168 their values.
2169 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002170 # unittest.TestCase has no skip mechanism
2171 if OP_NO_QUERY_MTU is not None:
2172 def test_op_no_query_mtu(self):
2173 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002174 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002175 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002176 """
2177 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
2178 else:
2179 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002180
2181
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002182 if OP_COOKIE_EXCHANGE is not None:
2183 def test_op_cookie_exchange(self):
2184 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002185 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002186 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002187 """
2188 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
2189 else:
2190 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002191
2192
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002193 if OP_NO_TICKET is not None:
2194 def test_op_no_ticket(self):
2195 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002196 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002197 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002198 """
2199 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04002200 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002201 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05002202
2203
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002204 if OP_NO_COMPRESSION is not None:
2205 def test_op_no_compression(self):
2206 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002207 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
2208 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002209 """
2210 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
2211 else:
2212 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
2213
2214
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002215 def test_sess_cache_off(self):
2216 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002217 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
2218 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002219 """
2220 self.assertEqual(0x0, SESS_CACHE_OFF)
2221
2222
2223 def test_sess_cache_client(self):
2224 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002225 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
2226 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002227 """
2228 self.assertEqual(0x1, SESS_CACHE_CLIENT)
2229
2230
2231 def test_sess_cache_server(self):
2232 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002233 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
2234 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002235 """
2236 self.assertEqual(0x2, SESS_CACHE_SERVER)
2237
2238
2239 def test_sess_cache_both(self):
2240 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002241 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
2242 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002243 """
2244 self.assertEqual(0x3, SESS_CACHE_BOTH)
2245
2246
2247 def test_sess_cache_no_auto_clear(self):
2248 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002249 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
2250 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
2251 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002252 """
2253 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
2254
2255
2256 def test_sess_cache_no_internal_lookup(self):
2257 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002258 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
2259 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
2260 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002261 """
2262 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
2263
2264
2265 def test_sess_cache_no_internal_store(self):
2266 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002267 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
2268 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
2269 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002270 """
2271 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
2272
2273
2274 def test_sess_cache_no_internal(self):
2275 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002276 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
2277 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
2278 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002279 """
2280 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
2281
2282
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04002283
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002284class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05002285 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002286 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05002287 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002288 def _server(self, sock):
2289 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002290 Create a new server-side SSL :py:obj:`Connection` object wrapped around
2291 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002292 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002293 # Create the server side Connection. This is mostly setup boilerplate
2294 # - use TLSv1, use a particular certificate, etc.
2295 server_ctx = Context(TLSv1_METHOD)
2296 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2297 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2298 server_store = server_ctx.get_cert_store()
2299 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2300 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2301 server_ctx.check_privatekey()
2302 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002303 # Here the Connection is actually created. If None is passed as the 2nd
2304 # parameter, it indicates a memory BIO should be created.
2305 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002306 server_conn.set_accept_state()
2307 return server_conn
2308
2309
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002310 def _client(self, sock):
2311 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002312 Create a new client-side SSL :py:obj:`Connection` object wrapped around
2313 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002314 """
2315 # Now create the client side Connection. Similar boilerplate to the
2316 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002317 client_ctx = Context(TLSv1_METHOD)
2318 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2319 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2320 client_store = client_ctx.get_cert_store()
2321 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
2322 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
2323 client_ctx.check_privatekey()
2324 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002325 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002326 client_conn.set_connect_state()
2327 return client_conn
2328
2329
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002330 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002331 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002332 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002333 reading from the output of each and writing those bytes to the input of
2334 the other and in this way establish a connection and exchange
2335 application-level bytes with each other.
2336 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002337 server_conn = self._server(None)
2338 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002339
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002340 # There should be no key or nonces yet.
2341 self.assertIdentical(server_conn.master_key(), None)
2342 self.assertIdentical(server_conn.client_random(), None)
2343 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002344
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002345 # First, the handshake needs to happen. We'll deliver bytes back and
2346 # forth between the client and server until neither of them feels like
2347 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002348 self.assertIdentical(
2349 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002350
2351 # Now that the handshake is done, there should be a key and nonces.
2352 self.assertNotIdentical(server_conn.master_key(), None)
2353 self.assertNotIdentical(server_conn.client_random(), None)
2354 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04002355 self.assertEquals(server_conn.client_random(), client_conn.client_random())
2356 self.assertEquals(server_conn.server_random(), client_conn.server_random())
2357 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
2358 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002359
2360 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002361 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05002362
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002363 server_conn.write(important_message)
2364 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002365 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002366 (client_conn, important_message))
2367
2368 client_conn.write(important_message[::-1])
2369 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002370 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002371 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05002372
2373
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002374 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05002375 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002376 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002377
2378 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09002379 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002380 this test fails, there must be a problem outside the memory BIO
2381 code, as no memory BIO is involved here). Even though this isn't a
2382 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05002383 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04002384 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05002385
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002386 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05002387 client_conn.send(important_message)
2388 msg = server_conn.recv(1024)
2389 self.assertEqual(msg, important_message)
2390
2391 # Again in the other direction, just for fun.
2392 important_message = important_message[::-1]
2393 server_conn.send(important_message)
2394 msg = client_conn.recv(1024)
2395 self.assertEqual(msg, important_message)
2396
2397
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04002398 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05002399 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002400 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
2401 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05002402 """
2403 context = Context(SSLv3_METHOD)
2404 client = socket()
2405 clientSSL = Connection(context, client)
2406 self.assertRaises( TypeError, clientSSL.bio_read, 100)
2407 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04002408 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002409
2410
2411 def test_outgoingOverflow(self):
2412 """
2413 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002414 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002415 returned and that many bytes from the beginning of the input can be
2416 read from the other end of the connection.
2417 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002418 server = self._server(None)
2419 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002420
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002421 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002422
2423 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002424 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002425 # Sanity check. We're trying to test what happens when the entire
2426 # input can't be sent. If the entire input was sent, this test is
2427 # meaningless.
2428 self.assertTrue(sent < size)
2429
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002430 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002431 self.assertIdentical(receiver, server)
2432
2433 # We can rely on all of these bytes being received at once because
2434 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
2435 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002436
2437
2438 def test_shutdown(self):
2439 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002440 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
2441 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002442 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002443 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002444 server.bio_shutdown()
2445 e = self.assertRaises(Error, server.recv, 1024)
2446 # We don't want WantReadError or ZeroReturnError or anything - it's a
2447 # handshake failure.
2448 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002449
2450
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002451 def test_unexpectedEndOfFile(self):
2452 """
2453 If the connection is lost before an orderly SSL shutdown occurs,
2454 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
2455 "Unexpected EOF".
2456 """
2457 server_conn, client_conn = self._loopback()
2458 client_conn.sock_shutdown(SHUT_RDWR)
2459 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
2460 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
2461
2462
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002463 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002464 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002465 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 -04002466
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002467 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002468 before the client and server are connected to each other. This
2469 function should specify a list of CAs for the server to send to the
2470 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09002471 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002472 times.
2473 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002474 server = self._server(None)
2475 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002476 self.assertEqual(client.get_client_ca_list(), [])
2477 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002478 ctx = server.get_context()
2479 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002480 self.assertEqual(client.get_client_ca_list(), [])
2481 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002482 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002483 self.assertEqual(client.get_client_ca_list(), expected)
2484 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002485
2486
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002487 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002488 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002489 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002490 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002491 """
2492 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002493 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
2494 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
2495 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002496
2497
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002498 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002499 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002500 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002501 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09002502 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002503 after the connection is set up.
2504 """
2505 def no_ca(ctx):
2506 ctx.set_client_ca_list([])
2507 return []
2508 self._check_client_ca_list(no_ca)
2509
2510
2511 def test_set_one_ca_list(self):
2512 """
2513 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002514 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002515 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002516 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002517 X509Name after the connection is set up.
2518 """
2519 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2520 cadesc = cacert.get_subject()
2521 def single_ca(ctx):
2522 ctx.set_client_ca_list([cadesc])
2523 return [cadesc]
2524 self._check_client_ca_list(single_ca)
2525
2526
2527 def test_set_multiple_ca_list(self):
2528 """
2529 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002530 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002531 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002532 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002533 X509Names after the connection is set up.
2534 """
2535 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2536 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2537
2538 sedesc = secert.get_subject()
2539 cldesc = clcert.get_subject()
2540
2541 def multiple_ca(ctx):
2542 L = [sedesc, cldesc]
2543 ctx.set_client_ca_list(L)
2544 return L
2545 self._check_client_ca_list(multiple_ca)
2546
2547
2548 def test_reset_ca_list(self):
2549 """
2550 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09002551 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002552 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002553 """
2554 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2555 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2556 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2557
2558 cadesc = cacert.get_subject()
2559 sedesc = secert.get_subject()
2560 cldesc = clcert.get_subject()
2561
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002562 def changed_ca(ctx):
2563 ctx.set_client_ca_list([sedesc, cldesc])
2564 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002565 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002566 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002567
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002568
2569 def test_mutated_ca_list(self):
2570 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002571 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002572 afterwards, this does not affect the list of CA names sent to the
2573 client.
2574 """
2575 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2576 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2577
2578 cadesc = cacert.get_subject()
2579 sedesc = secert.get_subject()
2580
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002581 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002582 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002583 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002584 L.append(sedesc)
2585 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002586 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002587
2588
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002589 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002590 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002591 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002592 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002593 """
2594 ctx = Context(TLSv1_METHOD)
2595 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002596 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002597 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002598 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002599
2600
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002601 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002602 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002603 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09002604 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002605 """
2606 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2607 cadesc = cacert.get_subject()
2608 def single_ca(ctx):
2609 ctx.add_client_ca(cacert)
2610 return [cadesc]
2611 self._check_client_ca_list(single_ca)
2612
2613
2614 def test_multiple_add_client_ca(self):
2615 """
2616 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09002617 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002618 """
2619 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2620 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2621
2622 cadesc = cacert.get_subject()
2623 sedesc = secert.get_subject()
2624
2625 def multiple_ca(ctx):
2626 ctx.add_client_ca(cacert)
2627 ctx.add_client_ca(secert)
2628 return [cadesc, sedesc]
2629 self._check_client_ca_list(multiple_ca)
2630
2631
2632 def test_set_and_add_client_ca(self):
2633 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002634 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
2635 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002636 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002637 """
2638 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2639 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2640 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2641
2642 cadesc = cacert.get_subject()
2643 sedesc = secert.get_subject()
2644 cldesc = clcert.get_subject()
2645
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002646 def mixed_set_add_ca(ctx):
2647 ctx.set_client_ca_list([cadesc, sedesc])
2648 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002649 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002650 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002651
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002652
2653 def test_set_after_add_client_ca(self):
2654 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002655 A call to :py:obj:`Context.set_client_ca_list` after a call to
2656 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002657 call with the names specified by the latter cal.
2658 """
2659 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2660 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2661 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2662
2663 cadesc = cacert.get_subject()
2664 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002665
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002666 def set_replaces_add_ca(ctx):
2667 ctx.add_client_ca(clcert)
2668 ctx.set_client_ca_list([cadesc])
2669 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002670 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002671 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002672
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002673
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002674
2675class ConnectionBIOTests(TestCase):
2676 """
2677 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
2678 """
2679 def test_wantReadError(self):
2680 """
2681 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
2682 if there are no bytes available to be read from the BIO.
2683 """
2684 ctx = Context(TLSv1_METHOD)
2685 conn = Connection(ctx, None)
2686 self.assertRaises(WantReadError, conn.bio_read, 1024)
2687
2688
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002689 def test_buffer_size(self):
2690 """
2691 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
2692 number of bytes to read and return.
2693 """
2694 ctx = Context(TLSv1_METHOD)
2695 conn = Connection(ctx, None)
2696 conn.set_connect_state()
2697 try:
2698 conn.do_handshake()
2699 except WantReadError:
2700 pass
2701 data = conn.bio_read(2)
2702 self.assertEqual(2, len(data))
2703
2704
2705 if not PY3:
2706 def test_buffer_size_long(self):
2707 """
2708 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
2709 :py:obj:`long` as well as :py:obj:`int`.
2710 """
2711 ctx = Context(TLSv1_METHOD)
2712 conn = Connection(ctx, None)
2713 conn.set_connect_state()
2714 try:
2715 conn.do_handshake()
2716 except WantReadError:
2717 pass
2718 data = conn.bio_read(long(2))
2719 self.assertEqual(2, len(data))
2720
2721
2722
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002723
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04002724class InfoConstantTests(TestCase):
2725 """
2726 Tests for assorted constants exposed for use in info callbacks.
2727 """
2728 def test_integers(self):
2729 """
2730 All of the info constants are integers.
2731
2732 This is a very weak test. It would be nice to have one that actually
2733 verifies that as certain info events happen, the value passed to the
2734 info callback matches up with the constant exposed by OpenSSL.SSL.
2735 """
2736 for const in [
2737 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
2738 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
2739 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
2740 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
2741 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
2742 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
2743
2744 self.assertTrue(isinstance(const, int))
2745
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02002746
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002747if __name__ == '__main__':
2748 main()