blob: 369b1b642e60383ee752d37b19c69d81974b7bb1 [file] [log] [blame]
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05001# Copyright (C) Jean-Paul Calderone
2# See LICENSE for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04003
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04004"""
Jonathan Ballet648875f2011-07-16 14:14:58 +09005Unit tests for :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04006"""
7
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05008from gc import collect, get_referrers
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02009from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE, ESHUTDOWN
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040010from sys import platform, version_info
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070011from socket import SHUT_RDWR, error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040012from os import makedirs
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040013from os.path import join
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -040014from unittest import main
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040015from weakref import ref
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050016
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -040017from six import PY3, text_type, u
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050018
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040019from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080020from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040021from OpenSSL.crypto import dump_privatekey, load_privatekey
22from OpenSSL.crypto import dump_certificate, load_certificate
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)
38
39from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070040 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050041from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070042 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040043
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050044from OpenSSL.test.util import TestCase, b
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040045from OpenSSL.test.test_crypto import (
46 cleartextCertificatePEM, cleartextPrivateKeyPEM)
47from OpenSSL.test.test_crypto import (
48 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
49 root_cert_pem)
50
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050051try:
52 from OpenSSL.SSL import OP_NO_QUERY_MTU
53except ImportError:
54 OP_NO_QUERY_MTU = None
55try:
56 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
57except ImportError:
58 OP_COOKIE_EXCHANGE = None
59try:
60 from OpenSSL.SSL import OP_NO_TICKET
61except ImportError:
62 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040063
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040064try:
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -040065 from OpenSSL.SSL import OP_NO_COMPRESSION
66except ImportError:
67 OP_NO_COMPRESSION = None
68
69try:
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040070 from OpenSSL.SSL import MODE_RELEASE_BUFFERS
71except ImportError:
72 MODE_RELEASE_BUFFERS = None
73
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040074try:
75 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
76except ImportError:
77 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
78
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040079from OpenSSL.SSL import (
80 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
81 SSL_ST_OK, SSL_ST_RENEGOTIATE,
82 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
83 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
84 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
85 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040086
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040087# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
88# to use)
89dhparam = """\
90-----BEGIN DH PARAMETERS-----
91MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
92-----END DH PARAMETERS-----
93"""
94
95
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040096def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040097 return ok
98
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040099
Rick Deanb1ccd562009-07-09 23:52:39 -0500100def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400101 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400102 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400103 """
104 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500105 port = socket()
106 port.bind(('', 0))
107 port.listen(1)
108 client = socket()
109 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400110 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400111 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500112 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500113
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400114 # Let's pass some unencrypted data to make sure our socket connection is
115 # fine. Just one byte, so we don't have to worry about buffers getting
116 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400117 server.send(b("x"))
118 assert client.recv(1024) == b("x")
119 client.send(b("y"))
120 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500121
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400122 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400123 server.setblocking(False)
124 client.setblocking(False)
125
Rick Deanb1ccd562009-07-09 23:52:39 -0500126 return (server, client)
127
128
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400129
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400130def handshake(client, server):
131 conns = [client, server]
132 while conns:
133 for conn in conns:
134 try:
135 conn.do_handshake()
136 except WantReadError:
137 pass
138 else:
139 conns.remove(conn)
140
141
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400142def _create_certificate_chain():
143 """
144 Construct and return a chain of certificates.
145
146 1. A new self-signed certificate authority certificate (cacert)
147 2. A new intermediate certificate signed by cacert (icert)
148 3. A new server certificate signed by icert (scert)
149 """
150 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
151
152 # Step 1
153 cakey = PKey()
154 cakey.generate_key(TYPE_RSA, 512)
155 cacert = X509()
156 cacert.get_subject().commonName = "Authority Certificate"
157 cacert.set_issuer(cacert.get_subject())
158 cacert.set_pubkey(cakey)
159 cacert.set_notBefore(b("20000101000000Z"))
160 cacert.set_notAfter(b("20200101000000Z"))
161 cacert.add_extensions([caext])
162 cacert.set_serial_number(0)
163 cacert.sign(cakey, "sha1")
164
165 # Step 2
166 ikey = PKey()
167 ikey.generate_key(TYPE_RSA, 512)
168 icert = X509()
169 icert.get_subject().commonName = "Intermediate Certificate"
170 icert.set_issuer(cacert.get_subject())
171 icert.set_pubkey(ikey)
172 icert.set_notBefore(b("20000101000000Z"))
173 icert.set_notAfter(b("20200101000000Z"))
174 icert.add_extensions([caext])
175 icert.set_serial_number(0)
176 icert.sign(cakey, "sha1")
177
178 # Step 3
179 skey = PKey()
180 skey.generate_key(TYPE_RSA, 512)
181 scert = X509()
182 scert.get_subject().commonName = "Server Certificate"
183 scert.set_issuer(icert.get_subject())
184 scert.set_pubkey(skey)
185 scert.set_notBefore(b("20000101000000Z"))
186 scert.set_notAfter(b("20200101000000Z"))
187 scert.add_extensions([
188 X509Extension(b('basicConstraints'), True, b('CA:false'))])
189 scert.set_serial_number(0)
190 scert.sign(ikey, "sha1")
191
192 return [(cakey, cacert), (ikey, icert), (skey, scert)]
193
194
195
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400196class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400197 """
198 Helper mixin which defines methods for creating a connected socket pair and
199 for forcing two connected SSL sockets to talk to each other via memory BIOs.
200 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500201 def _loopbackClientFactory(self, socket):
202 client = Connection(Context(TLSv1_METHOD), socket)
203 client.set_connect_state()
204 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400205
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500206
207 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400208 ctx = Context(TLSv1_METHOD)
209 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
210 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500211 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400212 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500213 return server
214
215
216 def _loopback(self, serverFactory=None, clientFactory=None):
217 if serverFactory is None:
218 serverFactory = self._loopbackServerFactory
219 if clientFactory is None:
220 clientFactory = self._loopbackClientFactory
221
222 (server, client) = socket_pair()
223 server = serverFactory(server)
224 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400225
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400226 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400227
228 server.setblocking(True)
229 client.setblocking(True)
230 return server, client
231
232
233 def _interactInMemory(self, client_conn, server_conn):
234 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900235 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400236 objects. Copy bytes back and forth between their send/receive buffers
237 for as long as there is anything to copy. When there is nothing more
Jonathan Ballet648875f2011-07-16 14:14:58 +0900238 to copy, return :py:obj:`None`. If one of them actually manages to deliver
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400239 some application bytes, return a two-tuple of the connection from which
240 the bytes were read and the bytes themselves.
241 """
242 wrote = True
243 while wrote:
244 # Loop until neither side has anything to say
245 wrote = False
246
247 # Copy stuff from each side's send buffer to the other side's
248 # receive buffer.
249 for (read, write) in [(client_conn, server_conn),
250 (server_conn, client_conn)]:
251
252 # Give the side a chance to generate some more bytes, or
253 # succeed.
254 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400255 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400256 except WantReadError:
257 # It didn't succeed, so we'll hope it generated some
258 # output.
259 pass
260 else:
261 # It did succeed, so we'll stop now and let the caller deal
262 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400263 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400264
265 while True:
266 # Keep copying as long as there's more stuff there.
267 try:
268 dirty = read.bio_read(4096)
269 except WantReadError:
270 # Okay, nothing more waiting to be sent. Stop
271 # processing this send buffer.
272 break
273 else:
274 # Keep track of the fact that someone generated some
275 # output.
276 wrote = True
277 write.bio_write(dirty)
278
279
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400280 def _handshakeInMemory(self, client_conn, server_conn):
281 client_conn.set_connect_state()
282 server_conn.set_accept_state()
283
284 for conn in [client_conn, server_conn]:
285 try:
286 conn.do_handshake()
287 except WantReadError:
288 pass
289
290 self._interactInMemory(client_conn, server_conn)
291
292
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400293
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400294class VersionTests(TestCase):
295 """
296 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900297 :py:obj:`OpenSSL.SSL.SSLeay_version` and
298 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400299 """
300 def test_OPENSSL_VERSION_NUMBER(self):
301 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900302 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400303 byte and the patch, fix, minor, and major versions in the
304 nibbles above that.
305 """
306 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
307
308
309 def test_SSLeay_version(self):
310 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900311 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400312 one of a number of version strings based on that indicator.
313 """
314 versions = {}
315 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
316 SSLEAY_PLATFORM, SSLEAY_DIR]:
317 version = SSLeay_version(t)
318 versions[version] = t
319 self.assertTrue(isinstance(version, bytes))
320 self.assertEqual(len(versions), 5)
321
322
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400323
324class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400325 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900326 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400327 """
328 def test_method(self):
329 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900330 :py:obj:`Context` can be instantiated with one of :py:obj:`SSLv2_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400331 :py:obj:`SSLv3_METHOD`, :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
332 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400333 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400334 methods = [
335 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
336 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400337 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400338
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400339
340 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
341 for meth in maybe:
342 try:
343 Context(meth)
344 except (Error, ValueError):
345 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
346 # don't. Difficult to say in advance.
347 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400348
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400349 self.assertRaises(TypeError, Context, "")
350 self.assertRaises(ValueError, Context, 10)
351
352
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500353 if not PY3:
354 def test_method_long(self):
355 """
356 On Python 2 :py:class:`Context` accepts values of type
357 :py:obj:`long` as well as :py:obj:`int`.
358 """
359 Context(long(TLSv1_METHOD))
360
361
362
Rick Deane15b1472009-07-09 15:53:42 -0500363 def test_type(self):
364 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900365 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400366 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500367 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400368 self.assertIdentical(Context, ContextType)
369 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500370
371
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400372 def test_use_privatekey(self):
373 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900374 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400375 """
376 key = PKey()
377 key.generate_key(TYPE_RSA, 128)
378 ctx = Context(TLSv1_METHOD)
379 ctx.use_privatekey(key)
380 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400381
382
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800383 def test_use_privatekey_file_missing(self):
384 """
385 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error`
386 when passed the name of a file which does not exist.
387 """
388 ctx = Context(TLSv1_METHOD)
389 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
390
391
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500392 if not PY3:
393 def test_use_privatekey_file_long(self):
394 """
395 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
396 filetype of type :py:obj:`long` as well as :py:obj:`int`.
397 """
398 pemfile = self.mktemp()
399
400 key = PKey()
401 key.generate_key(TYPE_RSA, 128)
402
403 with open(pemfile, "wt") as pem:
404 pem.write(
405 dump_privatekey(FILETYPE_PEM, key).decode("ascii"))
406
407 ctx = Context(TLSv1_METHOD)
408 ctx.use_privatekey_file(pemfile, long(FILETYPE_PEM))
409
410
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800411 def test_use_certificate_wrong_args(self):
412 """
413 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
414 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as an
415 argument.
416 """
417 ctx = Context(TLSv1_METHOD)
418 self.assertRaises(TypeError, ctx.use_certificate)
419 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
420 self.assertRaises(TypeError, ctx.use_certificate, X509(), "hello, world")
421
422
423 def test_use_certificate_uninitialized(self):
424 """
425 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
426 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
427 initialized (ie, which does not actually have any certificate data).
428 """
429 ctx = Context(TLSv1_METHOD)
430 self.assertRaises(Error, ctx.use_certificate, X509())
431
432
433 def test_use_certificate(self):
434 """
435 :py:obj:`Context.use_certificate` sets the certificate which will be
436 used to identify connections created using the context.
437 """
438 # TODO
439 # Hard to assert anything. But we could set a privatekey then ask
440 # OpenSSL if the cert and key agree using check_privatekey. Then as
441 # long as check_privatekey works right we're good...
442 ctx = Context(TLSv1_METHOD)
443 ctx.use_certificate(load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
444
445
446 def test_use_certificate_file_wrong_args(self):
447 """
448 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
449 called with zero arguments or more than two arguments, or if the first
450 argument is not a byte string or the second argumnent is not an integer.
451 """
452 ctx = Context(TLSv1_METHOD)
453 self.assertRaises(TypeError, ctx.use_certificate_file)
454 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile", object())
455 self.assertRaises(
456 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM, object())
457 self.assertRaises(
458 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
459 self.assertRaises(
460 TypeError, ctx.use_certificate_file, b"somefile", object())
461
462
463 def test_use_certificate_file_missing(self):
464 """
465 :py:obj:`Context.use_certificate_file` raises
466 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does not
467 exist.
468 """
469 ctx = Context(TLSv1_METHOD)
470 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
471
472
473 def test_use_certificate_file(self):
474 """
475 :py:obj:`Context.use_certificate` sets the certificate which will be
476 used to identify connections created using the context.
477 """
478 # TODO
479 # Hard to assert anything. But we could set a privatekey then ask
480 # OpenSSL if the cert and key agree using check_privatekey. Then as
481 # long as check_privatekey works right we're good...
482 pem_filename = self.mktemp()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500483 with open(pem_filename, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800484 pem_file.write(cleartextCertificatePEM)
485
486 ctx = Context(TLSv1_METHOD)
487 ctx.use_certificate_file(pem_filename)
488
489
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500490 if not PY3:
491 def test_use_certificate_file_long(self):
492 """
493 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
494 filetype of type :py:obj:`long` as well as :py:obj:`int`.
495 """
496 pem_filename = self.mktemp()
497 with open(pem_filename, "wb") as pem_file:
498 pem_file.write(cleartextCertificatePEM)
499
500 ctx = Context(TLSv1_METHOD)
501 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
502
503
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400504 def test_set_app_data_wrong_args(self):
505 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900506 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called with other than
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400507 one argument.
508 """
509 context = Context(TLSv1_METHOD)
510 self.assertRaises(TypeError, context.set_app_data)
511 self.assertRaises(TypeError, context.set_app_data, None, None)
512
513
514 def test_get_app_data_wrong_args(self):
515 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900516 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400517 arguments.
518 """
519 context = Context(TLSv1_METHOD)
520 self.assertRaises(TypeError, context.get_app_data, None)
521
522
523 def test_app_data(self):
524 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900525 :py:obj:`Context.set_app_data` stores an object for later retrieval using
526 :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400527 """
528 app_data = object()
529 context = Context(TLSv1_METHOD)
530 context.set_app_data(app_data)
531 self.assertIdentical(context.get_app_data(), app_data)
532
533
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400534 def test_set_options_wrong_args(self):
535 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900536 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with the wrong
537 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400538 """
539 context = Context(TLSv1_METHOD)
540 self.assertRaises(TypeError, context.set_options)
541 self.assertRaises(TypeError, context.set_options, None)
542 self.assertRaises(TypeError, context.set_options, 1, None)
543
544
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500545 def test_set_options(self):
546 """
547 :py:obj:`Context.set_options` returns the new options value.
548 """
549 context = Context(TLSv1_METHOD)
550 options = context.set_options(OP_NO_SSLv2)
551 self.assertTrue(OP_NO_SSLv2 & options)
552
553
554 if not PY3:
555 def test_set_options_long(self):
556 """
557 On Python 2 :py:obj:`Context.set_options` accepts values of type
558 :py:obj:`long` as well as :py:obj:`int`.
559 """
560 context = Context(TLSv1_METHOD)
561 options = context.set_options(long(OP_NO_SSLv2))
562 self.assertTrue(OP_NO_SSLv2 & options)
563
564
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300565 def test_set_mode_wrong_args(self):
566 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400567 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with the wrong
568 number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300569 """
570 context = Context(TLSv1_METHOD)
571 self.assertRaises(TypeError, context.set_mode)
572 self.assertRaises(TypeError, context.set_mode, None)
573 self.assertRaises(TypeError, context.set_mode, 1, None)
574
575
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400576 if MODE_RELEASE_BUFFERS is not None:
577 def test_set_mode(self):
578 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400579 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the newly
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400580 set mode.
581 """
582 context = Context(TLSv1_METHOD)
583 self.assertTrue(
584 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500585
586 if not PY3:
587 def test_set_mode_long(self):
588 """
589 On Python 2 :py:obj:`Context.set_mode` accepts values of type
590 :py:obj:`long` as well as :py:obj:`int`.
591 """
592 context = Context(TLSv1_METHOD)
593 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
594 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400595 else:
596 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
597
598
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400599 def test_set_timeout_wrong_args(self):
600 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900601 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with the wrong
602 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400603 """
604 context = Context(TLSv1_METHOD)
605 self.assertRaises(TypeError, context.set_timeout)
606 self.assertRaises(TypeError, context.set_timeout, None)
607 self.assertRaises(TypeError, context.set_timeout, 1, None)
608
609
610 def test_get_timeout_wrong_args(self):
611 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900612 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400613 """
614 context = Context(TLSv1_METHOD)
615 self.assertRaises(TypeError, context.get_timeout, None)
616
617
618 def test_timeout(self):
619 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900620 :py:obj:`Context.set_timeout` sets the session timeout for all connections
621 created using the context object. :py:obj:`Context.get_timeout` retrieves this
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400622 value.
623 """
624 context = Context(TLSv1_METHOD)
625 context.set_timeout(1234)
626 self.assertEquals(context.get_timeout(), 1234)
627
628
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500629 if not PY3:
630 def test_timeout_long(self):
631 """
632 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
633 `long` as well as int.
634 """
635 context = Context(TLSv1_METHOD)
636 context.set_timeout(long(1234))
637 self.assertEquals(context.get_timeout(), 1234)
638
639
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400640 def test_set_verify_depth_wrong_args(self):
641 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900642 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called with the wrong
643 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400644 """
645 context = Context(TLSv1_METHOD)
646 self.assertRaises(TypeError, context.set_verify_depth)
647 self.assertRaises(TypeError, context.set_verify_depth, None)
648 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
649
650
651 def test_get_verify_depth_wrong_args(self):
652 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900653 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400654 """
655 context = Context(TLSv1_METHOD)
656 self.assertRaises(TypeError, context.get_verify_depth, None)
657
658
659 def test_verify_depth(self):
660 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900661 :py:obj:`Context.set_verify_depth` sets the number of certificates in a chain
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400662 to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900663 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400664 """
665 context = Context(TLSv1_METHOD)
666 context.set_verify_depth(11)
667 self.assertEquals(context.get_verify_depth(), 11)
668
669
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500670 if not PY3:
671 def test_verify_depth_long(self):
672 """
673 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
674 type `long` as well as int.
675 """
676 context = Context(TLSv1_METHOD)
677 context.set_verify_depth(long(11))
678 self.assertEquals(context.get_verify_depth(), 11)
679
680
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400681 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400682 """
683 Write a new private key out to a new file, encrypted using the given
684 passphrase. Return the path to the new file.
685 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400686 key = PKey()
687 key.generate_key(TYPE_RSA, 128)
688 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400689 fObj = open(pemFile, 'w')
690 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
691 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400692 fObj.close()
693 return pemFile
694
695
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400696 def test_set_passwd_cb_wrong_args(self):
697 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900698 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called with the
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400699 wrong arguments or with a non-callable first argument.
700 """
701 context = Context(TLSv1_METHOD)
702 self.assertRaises(TypeError, context.set_passwd_cb)
703 self.assertRaises(TypeError, context.set_passwd_cb, None)
704 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
705
706
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400707 def test_set_passwd_cb(self):
708 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900709 :py:obj:`Context.set_passwd_cb` accepts a callable which will be invoked when
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400710 a private key is loaded from an encrypted PEM.
711 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400712 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400713 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400714 calledWith = []
715 def passphraseCallback(maxlen, verify, extra):
716 calledWith.append((maxlen, verify, extra))
717 return passphrase
718 context = Context(TLSv1_METHOD)
719 context.set_passwd_cb(passphraseCallback)
720 context.use_privatekey_file(pemFile)
721 self.assertTrue(len(calledWith), 1)
722 self.assertTrue(isinstance(calledWith[0][0], int))
723 self.assertTrue(isinstance(calledWith[0][1], int))
724 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400725
726
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400727 def test_passwd_callback_exception(self):
728 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900729 :py:obj:`Context.use_privatekey_file` propagates any exception raised by the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400730 passphrase callback.
731 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400732 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400733 def passphraseCallback(maxlen, verify, extra):
734 raise RuntimeError("Sorry, I am a fail.")
735
736 context = Context(TLSv1_METHOD)
737 context.set_passwd_cb(passphraseCallback)
738 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
739
740
741 def test_passwd_callback_false(self):
742 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900743 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400744 passphrase callback returns a false value.
745 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400746 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400747 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500748 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400749
750 context = Context(TLSv1_METHOD)
751 context.set_passwd_cb(passphraseCallback)
752 self.assertRaises(Error, context.use_privatekey_file, pemFile)
753
754
755 def test_passwd_callback_non_string(self):
756 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900757 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400758 passphrase callback returns a true non-string value.
759 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400760 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400761 def passphraseCallback(maxlen, verify, extra):
762 return 10
763
764 context = Context(TLSv1_METHOD)
765 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800766 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400767
768
769 def test_passwd_callback_too_long(self):
770 """
771 If the passphrase returned by the passphrase callback returns a string
772 longer than the indicated maximum length, it is truncated.
773 """
774 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400775 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400776 pemFile = self._write_encrypted_pem(passphrase)
777 def passphraseCallback(maxlen, verify, extra):
778 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400779 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400780
781 context = Context(TLSv1_METHOD)
782 context.set_passwd_cb(passphraseCallback)
783 # This shall succeed because the truncated result is the correct
784 # passphrase.
785 context.use_privatekey_file(pemFile)
786
787
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400788 def test_set_info_callback(self):
789 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900790 :py:obj:`Context.set_info_callback` accepts a callable which will be invoked
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400791 when certain information about an SSL connection is available.
792 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500793 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400794
795 clientSSL = Connection(Context(TLSv1_METHOD), client)
796 clientSSL.set_connect_state()
797
798 called = []
799 def info(conn, where, ret):
800 called.append((conn, where, ret))
801 context = Context(TLSv1_METHOD)
802 context.set_info_callback(info)
803 context.use_certificate(
804 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
805 context.use_privatekey(
806 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
807
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400808 serverSSL = Connection(context, server)
809 serverSSL.set_accept_state()
810
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500811 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400812
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500813 # The callback must always be called with a Connection instance as the
814 # first argument. It would probably be better to split this into
815 # separate tests for client and server side info callbacks so we could
816 # assert it is called with the right Connection instance. It would
817 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500818 notConnections = [
819 conn for (conn, where, ret) in called
820 if not isinstance(conn, Connection)]
821 self.assertEqual(
822 [], notConnections,
823 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400824
825
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400826 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400827 """
828 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400829 its :py:obj:`load_verify_locations` method with the given arguments.
830 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400831 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500832 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400833
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400834 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400835 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400836 # Require that the server certificate verify properly or the
837 # connection will fail.
838 clientContext.set_verify(
839 VERIFY_PEER,
840 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
841
842 clientSSL = Connection(clientContext, client)
843 clientSSL.set_connect_state()
844
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400845 serverContext = Context(TLSv1_METHOD)
846 serverContext.use_certificate(
847 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
848 serverContext.use_privatekey(
849 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
850
851 serverSSL = Connection(serverContext, server)
852 serverSSL.set_accept_state()
853
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400854 # Without load_verify_locations above, the handshake
855 # will fail:
856 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
857 # 'certificate verify failed')]
858 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400859
860 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400861 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400862
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500863
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400864 def test_load_verify_file(self):
865 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900866 :py:obj:`Context.load_verify_locations` accepts a file name and uses the
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400867 certificates within for verification purposes.
868 """
869 cafile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400870 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400871 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400872 fObj.close()
873
874 self._load_verify_locations_test(cafile)
875
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400876
877 def test_load_verify_invalid_file(self):
878 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900879 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when passed a
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400880 non-existent cafile.
881 """
882 clientContext = Context(TLSv1_METHOD)
883 self.assertRaises(
884 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400885
886
887 def test_load_verify_directory(self):
888 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900889 :py:obj:`Context.load_verify_locations` accepts a directory name and uses
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400890 the certificates within for verification purposes.
891 """
892 capath = self.mktemp()
893 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400894 # Hash values computed manually with c_rehash to avoid depending on
895 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
896 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500897 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400898 cafile = join(capath, name)
899 fObj = open(cafile, 'w')
900 fObj.write(cleartextCertificatePEM.decode('ascii'))
901 fObj.close()
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400902
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400903 self._load_verify_locations_test(None, capath)
904
905
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400906 def test_load_verify_locations_wrong_args(self):
907 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900908 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if called with
909 the wrong number of arguments or with non-:py:obj:`str` arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400910 """
911 context = Context(TLSv1_METHOD)
912 self.assertRaises(TypeError, context.load_verify_locations)
913 self.assertRaises(TypeError, context.load_verify_locations, object())
914 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
915 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
916
917
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400918 if platform == "win32":
919 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400920 "See LP#404343 and LP#404344."
921 else:
922 def test_set_default_verify_paths(self):
923 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900924 :py:obj:`Context.set_default_verify_paths` causes the platform-specific CA
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400925 certificate locations to be used for verification purposes.
926 """
927 # Testing this requires a server with a certificate signed by one of
928 # the CAs in the platform CA location. Getting one of those costs
929 # money. Fortunately (or unfortunately, depending on your
930 # perspective), it's easy to think of a public server on the
931 # internet which has such a certificate. Connecting to the network
932 # in a unit test is bad, but it's the only way I can think of to
933 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400934
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400935 # Arg, verisign.com doesn't speak TLSv1
936 context = Context(SSLv3_METHOD)
937 context.set_default_verify_paths()
938 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +0200939 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400940 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400941
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400942 client = socket()
943 client.connect(('verisign.com', 443))
944 clientSSL = Connection(context, client)
945 clientSSL.set_connect_state()
946 clientSSL.do_handshake()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500947 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400948 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400949
950
951 def test_set_default_verify_paths_signature(self):
952 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900953 :py:obj:`Context.set_default_verify_paths` takes no arguments and raises
954 :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400955 """
956 context = Context(TLSv1_METHOD)
957 self.assertRaises(TypeError, context.set_default_verify_paths, None)
958 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
959 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500960
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400961
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500962 def test_add_extra_chain_cert_invalid_cert(self):
963 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900964 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if called with
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500965 other than one argument or if called with an object which is not an
Jonathan Ballet648875f2011-07-16 14:14:58 +0900966 instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500967 """
968 context = Context(TLSv1_METHOD)
969 self.assertRaises(TypeError, context.add_extra_chain_cert)
970 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
971 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
972
973
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400974 def _handshake_test(self, serverContext, clientContext):
975 """
976 Verify that a client and server created with the given contexts can
977 successfully handshake and communicate.
978 """
979 serverSocket, clientSocket = socket_pair()
980
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400981 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400982 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400983
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400984 client = Connection(clientContext, clientSocket)
985 client.set_connect_state()
986
987 # Make them talk to each other.
988 # self._interactInMemory(client, server)
989 for i in range(3):
990 for s in [client, server]:
991 try:
992 s.do_handshake()
993 except WantReadError:
994 pass
995
996
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400997 def test_set_verify_callback_connection_argument(self):
998 """
999 The first argument passed to the verify callback is the
1000 :py:class:`Connection` instance for which verification is taking place.
1001 """
1002 serverContext = Context(TLSv1_METHOD)
1003 serverContext.use_privatekey(
1004 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1005 serverContext.use_certificate(
1006 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1007 serverConnection = Connection(serverContext, None)
1008
1009 class VerifyCallback(object):
1010 def callback(self, connection, *args):
1011 self.connection = connection
1012 return 1
1013
1014 verify = VerifyCallback()
1015 clientContext = Context(TLSv1_METHOD)
1016 clientContext.set_verify(VERIFY_PEER, verify.callback)
1017 clientConnection = Connection(clientContext, None)
1018 clientConnection.set_connect_state()
1019
1020 self._handshakeInMemory(clientConnection, serverConnection)
1021
1022 self.assertIdentical(verify.connection, clientConnection)
1023
1024
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001025 def test_set_verify_callback_exception(self):
1026 """
1027 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1028 exception, verification fails and the exception is propagated to the
1029 caller of :py:obj:`Connection.do_handshake`.
1030 """
1031 serverContext = Context(TLSv1_METHOD)
1032 serverContext.use_privatekey(
1033 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1034 serverContext.use_certificate(
1035 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1036
1037 clientContext = Context(TLSv1_METHOD)
1038 def verify_callback(*args):
1039 raise Exception("silly verify failure")
1040 clientContext.set_verify(VERIFY_PEER, verify_callback)
1041
1042 exc = self.assertRaises(
1043 Exception, self._handshake_test, serverContext, clientContext)
1044 self.assertEqual("silly verify failure", str(exc))
1045
1046
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001047 def test_add_extra_chain_cert(self):
1048 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001049 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509` instance to add to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001050 the certificate chain.
1051
Jonathan Ballet648875f2011-07-16 14:14:58 +09001052 See :py:obj:`_create_certificate_chain` for the details of the certificate
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001053 chain tested.
1054
1055 The chain is tested by starting a server with scert and connecting
1056 to it with a client which trusts cacert and requires verification to
1057 succeed.
1058 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001059 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001060 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1061
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001062 # Dump the CA certificate to a file because that's the only way to load
1063 # it as a trusted CA in the client context.
1064 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001065 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001066 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001067 fObj.close()
1068
1069 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001070 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001071 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001072 fObj.close()
1073
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001074 # Create the server context
1075 serverContext = Context(TLSv1_METHOD)
1076 serverContext.use_privatekey(skey)
1077 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001078 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001079 serverContext.add_extra_chain_cert(icert)
1080
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001081 # Create the client
1082 clientContext = Context(TLSv1_METHOD)
1083 clientContext.set_verify(
1084 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001085 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001086
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001087 # Try it out.
1088 self._handshake_test(serverContext, clientContext)
1089
1090
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001091 def test_use_certificate_chain_file(self):
1092 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001093 :py:obj:`Context.use_certificate_chain_file` reads a certificate chain from
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001094 the specified file.
1095
1096 The chain is tested by starting a server with scert and connecting
1097 to it with a client which trusts cacert and requires verification to
1098 succeed.
1099 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001100 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001101 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1102
1103 # Write out the chain file.
1104 chainFile = self.mktemp()
Jean-Paul Calderoned8607982014-01-18 10:30:55 -05001105 fObj = open(chainFile, 'wb')
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001106 # Most specific to least general.
Jean-Paul Calderoned8607982014-01-18 10:30:55 -05001107 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1108 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1109 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001110 fObj.close()
1111
1112 serverContext = Context(TLSv1_METHOD)
1113 serverContext.use_certificate_chain_file(chainFile)
1114 serverContext.use_privatekey(skey)
1115
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001116 fObj = open('ca.pem', 'w')
1117 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001118 fObj.close()
1119
1120 clientContext = Context(TLSv1_METHOD)
1121 clientContext.set_verify(
1122 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001123 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001124
1125 self._handshake_test(serverContext, clientContext)
1126
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001127
1128 def test_use_certificate_chain_file_wrong_args(self):
1129 """
1130 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1131 if passed zero or more than one argument or when passed a non-byte
1132 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error` when
1133 passed a bad chain file name (for example, the name of a file which does
1134 not exist).
1135 """
1136 context = Context(TLSv1_METHOD)
1137 self.assertRaises(TypeError, context.use_certificate_chain_file)
1138 self.assertRaises(TypeError, context.use_certificate_chain_file, object())
1139 self.assertRaises(TypeError, context.use_certificate_chain_file, b"foo", object())
1140
1141 self.assertRaises(Error, context.use_certificate_chain_file, self.mktemp())
1142
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001143 # XXX load_client_ca
1144 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001145
1146 def test_get_verify_mode_wrong_args(self):
1147 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001148 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001149 arguments.
1150 """
1151 context = Context(TLSv1_METHOD)
1152 self.assertRaises(TypeError, context.get_verify_mode, None)
1153
1154
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001155 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001156 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001157 :py:obj:`Context.get_verify_mode` returns the verify mode flags previously
1158 passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001159 """
1160 context = Context(TLSv1_METHOD)
1161 self.assertEquals(context.get_verify_mode(), 0)
1162 context.set_verify(
1163 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1164 self.assertEquals(
1165 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1166
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001167
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001168 if not PY3:
1169 def test_set_verify_mode_long(self):
1170 """
1171 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1172 type :py:obj:`long` as well as :py:obj:`int`.
1173 """
1174 context = Context(TLSv1_METHOD)
1175 self.assertEquals(context.get_verify_mode(), 0)
1176 context.set_verify(
1177 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None)
1178 self.assertEquals(
1179 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1180
1181
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001182 def test_load_tmp_dh_wrong_args(self):
1183 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001184 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
1185 number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001186 """
1187 context = Context(TLSv1_METHOD)
1188 self.assertRaises(TypeError, context.load_tmp_dh)
1189 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1190 self.assertRaises(TypeError, context.load_tmp_dh, object())
1191
1192
1193 def test_load_tmp_dh_missing_file(self):
1194 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001195 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the specified file
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001196 does not exist.
1197 """
1198 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001199 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001200
1201
1202 def test_load_tmp_dh(self):
1203 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001204 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001205 specified file.
1206 """
1207 context = Context(TLSv1_METHOD)
1208 dhfilename = self.mktemp()
1209 dhfile = open(dhfilename, "w")
1210 dhfile.write(dhparam)
1211 dhfile.close()
1212 context.load_tmp_dh(dhfilename)
1213 # XXX What should I assert here? -exarkun
1214
1215
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001216 def test_set_cipher_list_bytes(self):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001217 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001218 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
1219 ciphers which connections created with the context object will be able
1220 to choose from.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001221 """
1222 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001223 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001224 conn = Connection(context, None)
1225 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001226
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001227
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001228 def test_set_cipher_list_text(self):
1229 """
1230 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
1231 the ciphers which connections created with the context object will be
1232 able to choose from.
1233 """
1234 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -05001235 context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001236 conn = Connection(context, None)
1237 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
1238
1239
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001240 def test_set_cipher_list_wrong_args(self):
1241 """
Jean-Paul Calderone17044832014-01-18 10:20:11 -05001242 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
1243 passed zero arguments or more than one argument or when passed a
1244 non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001245 passed an incorrect cipher list string.
1246 """
1247 context = Context(TLSv1_METHOD)
1248 self.assertRaises(TypeError, context.set_cipher_list)
1249 self.assertRaises(TypeError, context.set_cipher_list, object())
1250 self.assertRaises(TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object())
1251
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001252 self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001253
1254
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001255 def test_set_session_cache_mode_wrong_args(self):
1256 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001257 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1258 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001259 """
1260 context = Context(TLSv1_METHOD)
1261 self.assertRaises(TypeError, context.set_session_cache_mode)
1262 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1263
1264
1265 def test_get_session_cache_mode_wrong_args(self):
1266 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001267 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1268 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001269 """
1270 context = Context(TLSv1_METHOD)
1271 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1272
1273
1274 def test_session_cache_mode(self):
1275 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001276 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1277 cached. The setting can be retrieved via
1278 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001279 """
1280 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001281 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001282 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1283 self.assertEqual(SESS_CACHE_OFF, off)
1284 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1285
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001286 if not PY3:
1287 def test_session_cache_mode_long(self):
1288 """
1289 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1290 of type :py:obj:`long` as well as :py:obj:`int`.
1291 """
1292 context = Context(TLSv1_METHOD)
1293 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1294 self.assertEqual(
1295 SESS_CACHE_BOTH, context.get_session_cache_mode())
1296
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001297
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001298 def test_get_cert_store(self):
1299 """
1300 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store` instance.
1301 """
1302 context = Context(TLSv1_METHOD)
1303 store = context.get_cert_store()
1304 self.assertIsInstance(store, X509Store)
1305
1306
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001307
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001308class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1309 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001310 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
1311 :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001312 """
1313 def test_wrong_args(self):
1314 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001315 :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001316 with other than one argument.
1317 """
1318 context = Context(TLSv1_METHOD)
1319 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1320 self.assertRaises(
1321 TypeError, context.set_tlsext_servername_callback, 1, 2)
1322
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001323
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001324 def test_old_callback_forgotten(self):
1325 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001326 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001327 callback, the one it replaces is dereferenced.
1328 """
1329 def callback(connection):
1330 pass
1331
1332 def replacement(connection):
1333 pass
1334
1335 context = Context(TLSv1_METHOD)
1336 context.set_tlsext_servername_callback(callback)
1337
1338 tracker = ref(callback)
1339 del callback
1340
1341 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001342
1343 # One run of the garbage collector happens to work on CPython. PyPy
1344 # doesn't collect the underlying object until a second run for whatever
1345 # reason. That's fine, it still demonstrates our code has properly
1346 # dropped the reference.
1347 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001348 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001349
1350 callback = tracker()
1351 if callback is not None:
1352 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001353 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001354 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001355
1356
1357 def test_no_servername(self):
1358 """
1359 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001360 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
1361 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001362 """
1363 args = []
1364 def servername(conn):
1365 args.append((conn, conn.get_servername()))
1366 context = Context(TLSv1_METHOD)
1367 context.set_tlsext_servername_callback(servername)
1368
1369 # Lose our reference to it. The Context is responsible for keeping it
1370 # alive now.
1371 del servername
1372 collect()
1373
1374 # Necessary to actually accept the connection
1375 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1376 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1377
1378 # Do a little connection to trigger the logic
1379 server = Connection(context, None)
1380 server.set_accept_state()
1381
1382 client = Connection(Context(TLSv1_METHOD), None)
1383 client.set_connect_state()
1384
1385 self._interactInMemory(server, client)
1386
1387 self.assertEqual([(server, None)], args)
1388
1389
1390 def test_servername(self):
1391 """
1392 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +09001393 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
1394 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001395 """
1396 args = []
1397 def servername(conn):
1398 args.append((conn, conn.get_servername()))
1399 context = Context(TLSv1_METHOD)
1400 context.set_tlsext_servername_callback(servername)
1401
1402 # Necessary to actually accept the connection
1403 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1404 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1405
1406 # Do a little connection to trigger the logic
1407 server = Connection(context, None)
1408 server.set_accept_state()
1409
1410 client = Connection(Context(TLSv1_METHOD), None)
1411 client.set_connect_state()
1412 client.set_tlsext_host_name(b("foo1.example.com"))
1413
1414 self._interactInMemory(server, client)
1415
1416 self.assertEqual([(server, b("foo1.example.com"))], args)
1417
1418
1419
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001420class SessionTests(TestCase):
1421 """
1422 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1423 """
1424 def test_construction(self):
1425 """
1426 :py:class:`Session` can be constructed with no arguments, creating a new
1427 instance of that type.
1428 """
1429 new_session = Session()
1430 self.assertTrue(isinstance(new_session, Session))
1431
1432
1433 def test_construction_wrong_args(self):
1434 """
1435 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
1436 is raised.
1437 """
1438 self.assertRaises(TypeError, Session, 123)
1439 self.assertRaises(TypeError, Session, "hello")
1440 self.assertRaises(TypeError, Session, object())
1441
1442
1443
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001444class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05001445 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001446 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001447 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001448 # XXX get_peer_certificate -> None
1449 # XXX sock_shutdown
1450 # XXX master_key -> TypeError
1451 # XXX server_random -> TypeError
1452 # XXX state_string
1453 # XXX connect -> TypeError
1454 # XXX connect_ex -> TypeError
1455 # XXX set_connect_state -> TypeError
1456 # XXX set_accept_state -> TypeError
1457 # XXX renegotiate_pending
1458 # XXX do_handshake -> TypeError
1459 # XXX bio_read -> TypeError
1460 # XXX recv -> TypeError
1461 # XXX send -> TypeError
1462 # XXX bio_write -> TypeError
1463
Rick Deane15b1472009-07-09 15:53:42 -05001464 def test_type(self):
1465 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001466 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001467 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05001468 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001469 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05001470 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001471 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05001472
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001473
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001474 def test_get_context(self):
1475 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001476 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
1477 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001478 """
1479 context = Context(TLSv1_METHOD)
1480 connection = Connection(context, None)
1481 self.assertIdentical(connection.get_context(), context)
1482
1483
1484 def test_get_context_wrong_args(self):
1485 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001486 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001487 arguments.
1488 """
1489 connection = Connection(Context(TLSv1_METHOD), None)
1490 self.assertRaises(TypeError, connection.get_context, None)
1491
1492
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001493 def test_set_context_wrong_args(self):
1494 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001495 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
1496 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001497 than 1.
1498 """
1499 ctx = Context(TLSv1_METHOD)
1500 connection = Connection(ctx, None)
1501 self.assertRaises(TypeError, connection.set_context)
1502 self.assertRaises(TypeError, connection.set_context, object())
1503 self.assertRaises(TypeError, connection.set_context, "hello")
1504 self.assertRaises(TypeError, connection.set_context, 1)
1505 self.assertRaises(TypeError, connection.set_context, 1, 2)
1506 self.assertRaises(
1507 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
1508 self.assertIdentical(ctx, connection.get_context())
1509
1510
1511 def test_set_context(self):
1512 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001513 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001514 for the connection.
1515 """
1516 original = Context(SSLv23_METHOD)
1517 replacement = Context(TLSv1_METHOD)
1518 connection = Connection(original, None)
1519 connection.set_context(replacement)
1520 self.assertIdentical(replacement, connection.get_context())
1521 # Lose our references to the contexts, just in case the Connection isn't
1522 # properly managing its own contributions to their reference counts.
1523 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001524 collect()
1525
1526
1527 def test_set_tlsext_host_name_wrong_args(self):
1528 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001529 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001530 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09001531 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001532 """
1533 conn = Connection(Context(TLSv1_METHOD), None)
1534 self.assertRaises(TypeError, conn.set_tlsext_host_name)
1535 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
1536 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
1537 self.assertRaises(
1538 TypeError, conn.set_tlsext_host_name, b("with\0null"))
1539
1540 if version_info >= (3,):
1541 # On Python 3.x, don't accidentally implicitly convert from text.
1542 self.assertRaises(
1543 TypeError,
1544 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001545
1546
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001547 def test_get_servername_wrong_args(self):
1548 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001549 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001550 arguments.
1551 """
1552 connection = Connection(Context(TLSv1_METHOD), None)
1553 self.assertRaises(TypeError, connection.get_servername, object())
1554 self.assertRaises(TypeError, connection.get_servername, 1)
1555 self.assertRaises(TypeError, connection.get_servername, "hello")
1556
1557
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001558 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001559 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001560 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001561 immediate read.
1562 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001563 connection = Connection(Context(TLSv1_METHOD), None)
1564 self.assertEquals(connection.pending(), 0)
1565
1566
1567 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001568 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001569 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001570 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001571 connection = Connection(Context(TLSv1_METHOD), None)
1572 self.assertRaises(TypeError, connection.pending, None)
1573
1574
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001575 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001576 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001577 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001578 argument or with the wrong number of arguments.
1579 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001580 connection = Connection(Context(TLSv1_METHOD), socket())
1581 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001582 self.assertRaises(TypeError, connection.connect)
1583 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001584
1585
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001586 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001587 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001588 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001589 connect method raises it.
1590 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001591 client = socket()
1592 context = Context(TLSv1_METHOD)
1593 clientSSL = Connection(context, client)
1594 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04001595 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001596
1597
1598 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001599 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001600 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001601 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001602 port = socket()
1603 port.bind(('', 0))
1604 port.listen(3)
1605
1606 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001607 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
1608 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001609
1610
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001611 if platform == "darwin":
1612 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
1613 else:
1614 def test_connect_ex(self):
1615 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001616 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001617 errno instead of raising an exception.
1618 """
1619 port = socket()
1620 port.bind(('', 0))
1621 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001622
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001623 clientSSL = Connection(Context(TLSv1_METHOD), socket())
1624 clientSSL.setblocking(False)
1625 result = clientSSL.connect_ex(port.getsockname())
1626 expected = (EINPROGRESS, EWOULDBLOCK)
1627 self.assertTrue(
1628 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001629
1630
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001631 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001632 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001633 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001634 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001635 connection = Connection(Context(TLSv1_METHOD), socket())
1636 self.assertRaises(TypeError, connection.accept, None)
1637
1638
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001639 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001640 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001641 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
1642 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001643 connection originated from.
1644 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001645 ctx = Context(TLSv1_METHOD)
1646 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1647 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001648 port = socket()
1649 portSSL = Connection(ctx, port)
1650 portSSL.bind(('', 0))
1651 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001652
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001653 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001654
1655 # Calling portSSL.getsockname() here to get the server IP address sounds
1656 # great, but frequently fails on Windows.
1657 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001658
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001659 serverSSL, address = portSSL.accept()
1660
1661 self.assertTrue(isinstance(serverSSL, Connection))
1662 self.assertIdentical(serverSSL.get_context(), ctx)
1663 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001664
1665
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001666 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001667 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001668 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001669 number of arguments or with arguments other than integers.
1670 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001671 connection = Connection(Context(TLSv1_METHOD), None)
1672 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04001673 self.assertRaises(TypeError, connection.get_shutdown, None)
1674 self.assertRaises(TypeError, connection.set_shutdown)
1675 self.assertRaises(TypeError, connection.set_shutdown, None)
1676 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001677
1678
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001679 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001680 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001681 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001682 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001683 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001684 self.assertFalse(server.shutdown())
1685 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001686 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001687 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
1688 client.shutdown()
1689 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
1690 self.assertRaises(ZeroReturnError, server.recv, 1024)
1691 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001692
1693
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001694 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001695 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001696 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001697 process.
1698 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001699 connection = Connection(Context(TLSv1_METHOD), socket())
1700 connection.set_shutdown(RECEIVED_SHUTDOWN)
1701 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1702
1703
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05001704 if not PY3:
1705 def test_set_shutdown_long(self):
1706 """
1707 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
1708 of type :py:obj:`long` as well as :py:obj:`int`.
1709 """
1710 connection = Connection(Context(TLSv1_METHOD), socket())
1711 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
1712 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1713
1714
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001715 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001716 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001717 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
1718 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001719 with any arguments.
1720 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001721 conn = Connection(Context(TLSv1_METHOD), None)
1722 self.assertRaises(TypeError, conn.get_app_data, None)
1723 self.assertRaises(TypeError, conn.set_app_data)
1724 self.assertRaises(TypeError, conn.set_app_data, None, None)
1725
1726
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001727 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001728 """
1729 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001730 :py:obj:`Connection.set_app_data` and later retrieved with
1731 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001732 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001733 conn = Connection(Context(TLSv1_METHOD), None)
1734 app_data = object()
1735 conn.set_app_data(app_data)
1736 self.assertIdentical(conn.get_app_data(), app_data)
1737
1738
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001739 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001740 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001741 :py:obj:`Connection.makefile` is not implemented and calling that method raises
1742 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001743 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001744 conn = Connection(Context(TLSv1_METHOD), None)
1745 self.assertRaises(NotImplementedError, conn.makefile)
1746
1747
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001748 def test_get_peer_cert_chain_wrong_args(self):
1749 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001750 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001751 arguments.
1752 """
1753 conn = Connection(Context(TLSv1_METHOD), None)
1754 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
1755 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
1756 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
1757 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
1758
1759
1760 def test_get_peer_cert_chain(self):
1761 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001762 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001763 the connected server returned for the certification verification.
1764 """
1765 chain = _create_certificate_chain()
1766 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1767
1768 serverContext = Context(TLSv1_METHOD)
1769 serverContext.use_privatekey(skey)
1770 serverContext.use_certificate(scert)
1771 serverContext.add_extra_chain_cert(icert)
1772 serverContext.add_extra_chain_cert(cacert)
1773 server = Connection(serverContext, None)
1774 server.set_accept_state()
1775
1776 # Create the client
1777 clientContext = Context(TLSv1_METHOD)
1778 clientContext.set_verify(VERIFY_NONE, verify_cb)
1779 client = Connection(clientContext, None)
1780 client.set_connect_state()
1781
1782 self._interactInMemory(client, server)
1783
1784 chain = client.get_peer_cert_chain()
1785 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001786 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001787 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001788 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001789 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001790 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001791 "Authority Certificate", chain[2].get_subject().CN)
1792
1793
1794 def test_get_peer_cert_chain_none(self):
1795 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001796 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001797 certificate chain.
1798 """
1799 ctx = Context(TLSv1_METHOD)
1800 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1801 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1802 server = Connection(ctx, None)
1803 server.set_accept_state()
1804 client = Connection(Context(TLSv1_METHOD), None)
1805 client.set_connect_state()
1806 self._interactInMemory(client, server)
1807 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001808
1809
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001810 def test_get_session_wrong_args(self):
1811 """
1812 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
1813 with any arguments.
1814 """
1815 ctx = Context(TLSv1_METHOD)
1816 server = Connection(ctx, None)
1817 self.assertRaises(TypeError, server.get_session, 123)
1818 self.assertRaises(TypeError, server.get_session, "hello")
1819 self.assertRaises(TypeError, server.get_session, object())
1820
1821
1822 def test_get_session_unconnected(self):
1823 """
1824 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
1825 an object which has not been connected.
1826 """
1827 ctx = Context(TLSv1_METHOD)
1828 server = Connection(ctx, None)
1829 session = server.get_session()
1830 self.assertIdentical(None, session)
1831
1832
1833 def test_server_get_session(self):
1834 """
1835 On the server side of a connection, :py:obj:`Connection.get_session`
1836 returns a :py:class:`Session` instance representing the SSL session for
1837 that connection.
1838 """
1839 server, client = self._loopback()
1840 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001841 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001842
1843
1844 def test_client_get_session(self):
1845 """
1846 On the client side of a connection, :py:obj:`Connection.get_session`
1847 returns a :py:class:`Session` instance representing the SSL session for
1848 that connection.
1849 """
1850 server, client = self._loopback()
1851 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001852 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001853
1854
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05001855 def test_set_session_wrong_args(self):
1856 """
1857 If called with an object that is not an instance of :py:class:`Session`,
1858 or with other than one argument, :py:obj:`Connection.set_session` raises
1859 :py:obj:`TypeError`.
1860 """
1861 ctx = Context(TLSv1_METHOD)
1862 connection = Connection(ctx, None)
1863 self.assertRaises(TypeError, connection.set_session)
1864 self.assertRaises(TypeError, connection.set_session, 123)
1865 self.assertRaises(TypeError, connection.set_session, "hello")
1866 self.assertRaises(TypeError, connection.set_session, object())
1867 self.assertRaises(
1868 TypeError, connection.set_session, Session(), Session())
1869
1870
1871 def test_client_set_session(self):
1872 """
1873 :py:obj:`Connection.set_session`, when used prior to a connection being
1874 established, accepts a :py:class:`Session` instance and causes an
1875 attempt to re-use the session it represents when the SSL handshake is
1876 performed.
1877 """
1878 key = load_privatekey(FILETYPE_PEM, server_key_pem)
1879 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
1880 ctx = Context(TLSv1_METHOD)
1881 ctx.use_privatekey(key)
1882 ctx.use_certificate(cert)
1883 ctx.set_session_id("unity-test")
1884
1885 def makeServer(socket):
1886 server = Connection(ctx, socket)
1887 server.set_accept_state()
1888 return server
1889
1890 originalServer, originalClient = self._loopback(
1891 serverFactory=makeServer)
1892 originalSession = originalClient.get_session()
1893
1894 def makeClient(socket):
1895 client = self._loopbackClientFactory(socket)
1896 client.set_session(originalSession)
1897 return client
1898 resumedServer, resumedClient = self._loopback(
1899 serverFactory=makeServer,
1900 clientFactory=makeClient)
1901
1902 # This is a proxy: in general, we have no access to any unique
1903 # identifier for the session (new enough versions of OpenSSL expose a
1904 # hash which could be usable, but "new enough" is very, very new).
1905 # Instead, exploit the fact that the master key is re-used if the
1906 # session is re-used. As long as the master key for the two connections
1907 # is the same, the session was re-used!
1908 self.assertEqual(
1909 originalServer.master_key(), resumedServer.master_key())
1910
1911
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05001912 def test_set_session_wrong_method(self):
1913 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05001914 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
1915 instance associated with a context using a different SSL method than the
1916 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
1917 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05001918 """
1919 key = load_privatekey(FILETYPE_PEM, server_key_pem)
1920 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
1921 ctx = Context(TLSv1_METHOD)
1922 ctx.use_privatekey(key)
1923 ctx.use_certificate(cert)
1924 ctx.set_session_id("unity-test")
1925
1926 def makeServer(socket):
1927 server = Connection(ctx, socket)
1928 server.set_accept_state()
1929 return server
1930
1931 originalServer, originalClient = self._loopback(
1932 serverFactory=makeServer)
1933 originalSession = originalClient.get_session()
1934
1935 def makeClient(socket):
1936 # Intentionally use a different, incompatible method here.
1937 client = Connection(Context(SSLv3_METHOD), socket)
1938 client.set_connect_state()
1939 client.set_session(originalSession)
1940 return client
1941
1942 self.assertRaises(
1943 Error,
1944 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
1945
1946
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07001947 def test_wantWriteError(self):
1948 """
1949 :py:obj:`Connection` methods which generate output raise
1950 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
1951 fail indicating a should-write state.
1952 """
1953 client_socket, server_socket = socket_pair()
1954 # Fill up the client's send buffer so Connection won't be able to write
1955 # anything.
Jean-Paul Calderone7d7c9c22014-02-18 16:38:26 -05001956 msg = b"x" * 512
Jean-Paul Calderone22c28b42014-02-18 16:40:34 -05001957 for i in range(2048):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07001958 try:
1959 client_socket.send(msg)
1960 except error as e:
1961 if e.errno == EWOULDBLOCK:
1962 break
1963 raise
1964 else:
1965 self.fail(
1966 "Failed to fill socket buffer, cannot test BIO want write")
1967
1968 ctx = Context(TLSv1_METHOD)
1969 conn = Connection(ctx, client_socket)
1970 # Client's speak first, so make it an SSL client
1971 conn.set_connect_state()
1972 self.assertRaises(WantWriteError, conn.do_handshake)
1973
1974 # XXX want_read
1975
Fedor Brunner416f4a12014-03-28 13:18:38 +01001976 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01001977 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04001978 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
1979 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01001980 """
Fedor Brunner5747b932014-03-05 14:22:34 +01001981 ctx = Context(TLSv1_METHOD)
1982 connection = Connection(ctx, None)
1983 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01001984
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04001985
Fedor Brunner416f4a12014-03-28 13:18:38 +01001986 def test_get_peer_finished_before_connect(self):
1987 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04001988 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
1989 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01001990 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01001991 ctx = Context(TLSv1_METHOD)
1992 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01001993 self.assertEqual(connection.get_peer_finished(), None)
1994
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04001995
Fedor Brunner416f4a12014-03-28 13:18:38 +01001996 def test_get_finished(self):
1997 """
1998 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04001999 message send from client, or server. Finished messages are send during
2000 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002001 """
2002
Fedor Brunner5747b932014-03-05 14:22:34 +01002003 server, client = self._loopback()
2004
2005 self.assertNotEqual(server.get_finished(), None)
2006 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002007
Jean-Paul Calderoned979f232014-03-30 11:58:00 -04002008
Fedor Brunner416f4a12014-03-28 13:18:38 +01002009 def test_get_peer_finished(self):
2010 """
2011 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002012 message received from client, or server. Finished messages are send
2013 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002014 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002015 server, client = self._loopback()
2016
2017 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002018 self.assertTrue(len(server.get_peer_finished()) > 0)
2019
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002020
Fedor Brunner416f4a12014-03-28 13:18:38 +01002021 def test_tls_finished_message_symmetry(self):
2022 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002023 The TLS Finished message send by server must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002024 received by client.
2025
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002026 The TLS Finished message send by client must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002027 received by server.
2028 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002029 server, client = self._loopback()
2030
Fedor Brunner5747b932014-03-05 14:22:34 +01002031 self.assertEqual(server.get_finished(), client.get_peer_finished())
2032 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002033
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002034
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002035 def test_get_cipher_name_before_connect(self):
2036 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002037 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2038 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002039 """
2040 ctx = Context(TLSv1_METHOD)
2041 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002042 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002043
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002044
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002045 def test_get_cipher_name(self):
2046 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002047 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2048 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002049 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002050 server, client = self._loopback()
2051 server_cipher_name, client_cipher_name = \
2052 server.get_cipher_name(), client.get_cipher_name()
2053
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002054 self.assertIsInstance(server_cipher_name, text_type)
2055 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002056
2057 self.assertEqual(server_cipher_name, client_cipher_name)
2058
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002059
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002060 def test_get_cipher_version_before_connect(self):
2061 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002062 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2063 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002064 """
2065 ctx = Context(TLSv1_METHOD)
2066 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002067 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002068
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002069
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002070 def test_get_cipher_version(self):
2071 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002072 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2073 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002074 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002075 server, client = self._loopback()
2076 server_cipher_version, client_cipher_version = \
2077 server.get_cipher_version(), client.get_cipher_version()
2078
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002079 self.assertIsInstance(server_cipher_version, text_type)
2080 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002081
2082 self.assertEqual(server_cipher_version, client_cipher_version)
2083
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002084
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002085 def test_get_cipher_bits_before_connect(self):
2086 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002087 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2088 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002089 """
2090 ctx = Context(TLSv1_METHOD)
2091 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002092 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002093
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002094
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002095 def test_get_cipher_bits(self):
2096 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002097 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2098 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002099 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002100 server, client = self._loopback()
2101 server_cipher_bits, client_cipher_bits = \
2102 server.get_cipher_bits(), client.get_cipher_bits()
2103
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002104 self.assertIsInstance(server_cipher_bits, int)
2105 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002106
2107 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002108
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002109
2110
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002111class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002112 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002113 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002114 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002115 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002116 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002117 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002118 arguments.
2119 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002120 connection = Connection(Context(TLSv1_METHOD), None)
2121 self.assertRaises(TypeError, connection.get_cipher_list, None)
2122
2123
2124 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002125 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002126 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2127 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002128 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002129 connection = Connection(Context(TLSv1_METHOD), None)
2130 ciphers = connection.get_cipher_list()
2131 self.assertTrue(isinstance(ciphers, list))
2132 for cipher in ciphers:
2133 self.assertTrue(isinstance(cipher, str))
2134
2135
2136
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002137class ConnectionSendTests(TestCase, _LoopbackMixin):
2138 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002139 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002140 """
2141 def test_wrong_args(self):
2142 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002143 When called with arguments other than string argument for its first
2144 parameter or more than two arguments, :py:obj:`Connection.send` raises
2145 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002146 """
2147 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002148 self.assertRaises(TypeError, connection.send)
2149 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002150 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002151
2152
2153 def test_short_bytes(self):
2154 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002155 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002156 and returns the number of bytes sent.
2157 """
2158 server, client = self._loopback()
2159 count = server.send(b('xy'))
2160 self.assertEquals(count, 2)
2161 self.assertEquals(client.recv(2), b('xy'))
2162
2163 try:
2164 memoryview
2165 except NameError:
2166 "cannot test sending memoryview without memoryview"
2167 else:
2168 def test_short_memoryview(self):
2169 """
2170 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002171 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002172 bytes sent.
2173 """
2174 server, client = self._loopback()
2175 count = server.send(memoryview(b('xy')))
2176 self.assertEquals(count, 2)
2177 self.assertEquals(client.recv(2), b('xy'))
2178
2179
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002180
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002181class ConnectionSendallTests(TestCase, _LoopbackMixin):
2182 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002183 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002184 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002185 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002186 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002187 When called with arguments other than a string argument for its first
2188 parameter or with more than two arguments, :py:obj:`Connection.sendall`
2189 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002190 """
2191 connection = Connection(Context(TLSv1_METHOD), None)
2192 self.assertRaises(TypeError, connection.sendall)
2193 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002194 self.assertRaises(
2195 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002196
2197
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002198 def test_short(self):
2199 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002200 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002201 it.
2202 """
2203 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04002204 server.sendall(b('x'))
2205 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002206
2207
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002208 try:
2209 memoryview
2210 except NameError:
2211 "cannot test sending memoryview without memoryview"
2212 else:
2213 def test_short_memoryview(self):
2214 """
2215 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002216 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002217 """
2218 server, client = self._loopback()
2219 server.sendall(memoryview(b('x')))
2220 self.assertEquals(client.recv(1), b('x'))
2221
2222
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002223 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002224 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002225 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002226 it even if this requires multiple calls of an underlying write function.
2227 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002228 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04002229 # Should be enough, underlying SSL_write should only do 16k at a time.
2230 # On Windows, after 32k of bytes the write will block (forever - because
2231 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04002232 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002233 server.sendall(message)
2234 accum = []
2235 received = 0
2236 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04002237 data = client.recv(1024)
2238 accum.append(data)
2239 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04002240 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002241
2242
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002243 def test_closed(self):
2244 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002245 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002246 write error from the low level write call.
2247 """
2248 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04002249 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002250 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02002251 if platform == "win32":
2252 self.assertEqual(exc.args[0], ESHUTDOWN)
2253 else:
2254 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002255
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002256
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002257
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002258class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
2259 """
2260 Tests for SSL renegotiation APIs.
2261 """
2262 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002263 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002264 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002265 arguments.
2266 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002267 connection = Connection(Context(TLSv1_METHOD), None)
2268 self.assertRaises(TypeError, connection.renegotiate, None)
2269
2270
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002271 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002272 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002273 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002274 any arguments.
2275 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002276 connection = Connection(Context(TLSv1_METHOD), None)
2277 self.assertRaises(TypeError, connection.total_renegotiations, None)
2278
2279
2280 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002281 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002282 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002283 renegotiations have happened.
2284 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002285 connection = Connection(Context(TLSv1_METHOD), None)
2286 self.assertEquals(connection.total_renegotiations(), 0)
2287
2288
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002289# def test_renegotiate(self):
2290# """
2291# """
2292# server, client = self._loopback()
2293
2294# server.send("hello world")
2295# self.assertEquals(client.recv(len("hello world")), "hello world")
2296
2297# self.assertEquals(server.total_renegotiations(), 0)
2298# self.assertTrue(server.renegotiate())
2299
2300# server.setblocking(False)
2301# client.setblocking(False)
2302# while server.renegotiate_pending():
2303# client.do_handshake()
2304# server.do_handshake()
2305
2306# self.assertEquals(server.total_renegotiations(), 1)
2307
2308
2309
2310
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002311class ErrorTests(TestCase):
2312 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002313 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002314 """
2315 def test_type(self):
2316 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002317 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002318 """
2319 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05002320 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05002321
2322
2323
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002324class ConstantsTests(TestCase):
2325 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002326 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002327
2328 These are values defined by OpenSSL intended only to be used as flags to
2329 OpenSSL APIs. The only assertions it seems can be made about them is
2330 their values.
2331 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002332 # unittest.TestCase has no skip mechanism
2333 if OP_NO_QUERY_MTU is not None:
2334 def test_op_no_query_mtu(self):
2335 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002336 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002337 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002338 """
2339 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
2340 else:
2341 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002342
2343
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002344 if OP_COOKIE_EXCHANGE is not None:
2345 def test_op_cookie_exchange(self):
2346 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002347 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002348 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002349 """
2350 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
2351 else:
2352 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002353
2354
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002355 if OP_NO_TICKET is not None:
2356 def test_op_no_ticket(self):
2357 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002358 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002359 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002360 """
2361 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04002362 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002363 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05002364
2365
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002366 if OP_NO_COMPRESSION is not None:
2367 def test_op_no_compression(self):
2368 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002369 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
2370 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002371 """
2372 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
2373 else:
2374 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
2375
2376
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002377 def test_sess_cache_off(self):
2378 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002379 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
2380 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002381 """
2382 self.assertEqual(0x0, SESS_CACHE_OFF)
2383
2384
2385 def test_sess_cache_client(self):
2386 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002387 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
2388 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002389 """
2390 self.assertEqual(0x1, SESS_CACHE_CLIENT)
2391
2392
2393 def test_sess_cache_server(self):
2394 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002395 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
2396 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002397 """
2398 self.assertEqual(0x2, SESS_CACHE_SERVER)
2399
2400
2401 def test_sess_cache_both(self):
2402 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002403 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
2404 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002405 """
2406 self.assertEqual(0x3, SESS_CACHE_BOTH)
2407
2408
2409 def test_sess_cache_no_auto_clear(self):
2410 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002411 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
2412 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
2413 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002414 """
2415 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
2416
2417
2418 def test_sess_cache_no_internal_lookup(self):
2419 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002420 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
2421 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
2422 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002423 """
2424 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
2425
2426
2427 def test_sess_cache_no_internal_store(self):
2428 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002429 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
2430 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
2431 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002432 """
2433 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
2434
2435
2436 def test_sess_cache_no_internal(self):
2437 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002438 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
2439 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
2440 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002441 """
2442 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
2443
2444
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04002445
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002446class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05002447 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002448 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05002449 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002450 def _server(self, sock):
2451 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002452 Create a new server-side SSL :py:obj:`Connection` object wrapped around
2453 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002454 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002455 # Create the server side Connection. This is mostly setup boilerplate
2456 # - use TLSv1, use a particular certificate, etc.
2457 server_ctx = Context(TLSv1_METHOD)
2458 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2459 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2460 server_store = server_ctx.get_cert_store()
2461 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2462 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2463 server_ctx.check_privatekey()
2464 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002465 # Here the Connection is actually created. If None is passed as the 2nd
2466 # parameter, it indicates a memory BIO should be created.
2467 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002468 server_conn.set_accept_state()
2469 return server_conn
2470
2471
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002472 def _client(self, sock):
2473 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002474 Create a new client-side SSL :py:obj:`Connection` object wrapped around
2475 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002476 """
2477 # Now create the client side Connection. Similar boilerplate to the
2478 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002479 client_ctx = Context(TLSv1_METHOD)
2480 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2481 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2482 client_store = client_ctx.get_cert_store()
2483 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
2484 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
2485 client_ctx.check_privatekey()
2486 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002487 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002488 client_conn.set_connect_state()
2489 return client_conn
2490
2491
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002492 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002493 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002494 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002495 reading from the output of each and writing those bytes to the input of
2496 the other and in this way establish a connection and exchange
2497 application-level bytes with each other.
2498 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002499 server_conn = self._server(None)
2500 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002501
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002502 # There should be no key or nonces yet.
2503 self.assertIdentical(server_conn.master_key(), None)
2504 self.assertIdentical(server_conn.client_random(), None)
2505 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002506
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002507 # First, the handshake needs to happen. We'll deliver bytes back and
2508 # forth between the client and server until neither of them feels like
2509 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002510 self.assertIdentical(
2511 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002512
2513 # Now that the handshake is done, there should be a key and nonces.
2514 self.assertNotIdentical(server_conn.master_key(), None)
2515 self.assertNotIdentical(server_conn.client_random(), None)
2516 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04002517 self.assertEquals(server_conn.client_random(), client_conn.client_random())
2518 self.assertEquals(server_conn.server_random(), client_conn.server_random())
2519 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
2520 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002521
2522 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002523 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05002524
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002525 server_conn.write(important_message)
2526 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002527 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002528 (client_conn, important_message))
2529
2530 client_conn.write(important_message[::-1])
2531 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002532 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002533 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05002534
2535
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002536 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05002537 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002538 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002539
2540 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09002541 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002542 this test fails, there must be a problem outside the memory BIO
2543 code, as no memory BIO is involved here). Even though this isn't a
2544 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05002545 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04002546 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05002547
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002548 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05002549 client_conn.send(important_message)
2550 msg = server_conn.recv(1024)
2551 self.assertEqual(msg, important_message)
2552
2553 # Again in the other direction, just for fun.
2554 important_message = important_message[::-1]
2555 server_conn.send(important_message)
2556 msg = client_conn.recv(1024)
2557 self.assertEqual(msg, important_message)
2558
2559
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04002560 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05002561 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002562 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
2563 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05002564 """
2565 context = Context(SSLv3_METHOD)
2566 client = socket()
2567 clientSSL = Connection(context, client)
2568 self.assertRaises( TypeError, clientSSL.bio_read, 100)
2569 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04002570 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002571
2572
2573 def test_outgoingOverflow(self):
2574 """
2575 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002576 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002577 returned and that many bytes from the beginning of the input can be
2578 read from the other end of the connection.
2579 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002580 server = self._server(None)
2581 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002582
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002583 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002584
2585 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002586 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002587 # Sanity check. We're trying to test what happens when the entire
2588 # input can't be sent. If the entire input was sent, this test is
2589 # meaningless.
2590 self.assertTrue(sent < size)
2591
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002592 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002593 self.assertIdentical(receiver, server)
2594
2595 # We can rely on all of these bytes being received at once because
2596 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
2597 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002598
2599
2600 def test_shutdown(self):
2601 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002602 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
2603 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002604 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002605 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002606 server.bio_shutdown()
2607 e = self.assertRaises(Error, server.recv, 1024)
2608 # We don't want WantReadError or ZeroReturnError or anything - it's a
2609 # handshake failure.
2610 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002611
2612
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002613 def test_unexpectedEndOfFile(self):
2614 """
2615 If the connection is lost before an orderly SSL shutdown occurs,
2616 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
2617 "Unexpected EOF".
2618 """
2619 server_conn, client_conn = self._loopback()
2620 client_conn.sock_shutdown(SHUT_RDWR)
2621 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
2622 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
2623
2624
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002625 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002626 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002627 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 -04002628
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002629 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002630 before the client and server are connected to each other. This
2631 function should specify a list of CAs for the server to send to the
2632 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09002633 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002634 times.
2635 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002636 server = self._server(None)
2637 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002638 self.assertEqual(client.get_client_ca_list(), [])
2639 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002640 ctx = server.get_context()
2641 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002642 self.assertEqual(client.get_client_ca_list(), [])
2643 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002644 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002645 self.assertEqual(client.get_client_ca_list(), expected)
2646 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002647
2648
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002649 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002650 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002651 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002652 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002653 """
2654 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002655 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
2656 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
2657 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002658
2659
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002660 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002661 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002662 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002663 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09002664 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002665 after the connection is set up.
2666 """
2667 def no_ca(ctx):
2668 ctx.set_client_ca_list([])
2669 return []
2670 self._check_client_ca_list(no_ca)
2671
2672
2673 def test_set_one_ca_list(self):
2674 """
2675 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002676 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002677 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002678 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002679 X509Name after the connection is set up.
2680 """
2681 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2682 cadesc = cacert.get_subject()
2683 def single_ca(ctx):
2684 ctx.set_client_ca_list([cadesc])
2685 return [cadesc]
2686 self._check_client_ca_list(single_ca)
2687
2688
2689 def test_set_multiple_ca_list(self):
2690 """
2691 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002692 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002693 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002694 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002695 X509Names after the connection is set up.
2696 """
2697 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2698 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2699
2700 sedesc = secert.get_subject()
2701 cldesc = clcert.get_subject()
2702
2703 def multiple_ca(ctx):
2704 L = [sedesc, cldesc]
2705 ctx.set_client_ca_list(L)
2706 return L
2707 self._check_client_ca_list(multiple_ca)
2708
2709
2710 def test_reset_ca_list(self):
2711 """
2712 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09002713 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002714 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002715 """
2716 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2717 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2718 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2719
2720 cadesc = cacert.get_subject()
2721 sedesc = secert.get_subject()
2722 cldesc = clcert.get_subject()
2723
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002724 def changed_ca(ctx):
2725 ctx.set_client_ca_list([sedesc, cldesc])
2726 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002727 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002728 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002729
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002730
2731 def test_mutated_ca_list(self):
2732 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002733 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002734 afterwards, this does not affect the list of CA names sent to the
2735 client.
2736 """
2737 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2738 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2739
2740 cadesc = cacert.get_subject()
2741 sedesc = secert.get_subject()
2742
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002743 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002744 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002745 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002746 L.append(sedesc)
2747 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002748 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002749
2750
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002751 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002752 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002753 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002754 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002755 """
2756 ctx = Context(TLSv1_METHOD)
2757 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002758 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002759 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002760 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002761
2762
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002763 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002764 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002765 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09002766 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002767 """
2768 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2769 cadesc = cacert.get_subject()
2770 def single_ca(ctx):
2771 ctx.add_client_ca(cacert)
2772 return [cadesc]
2773 self._check_client_ca_list(single_ca)
2774
2775
2776 def test_multiple_add_client_ca(self):
2777 """
2778 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09002779 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002780 """
2781 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2782 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2783
2784 cadesc = cacert.get_subject()
2785 sedesc = secert.get_subject()
2786
2787 def multiple_ca(ctx):
2788 ctx.add_client_ca(cacert)
2789 ctx.add_client_ca(secert)
2790 return [cadesc, sedesc]
2791 self._check_client_ca_list(multiple_ca)
2792
2793
2794 def test_set_and_add_client_ca(self):
2795 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002796 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
2797 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002798 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002799 """
2800 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2801 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2802 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2803
2804 cadesc = cacert.get_subject()
2805 sedesc = secert.get_subject()
2806 cldesc = clcert.get_subject()
2807
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002808 def mixed_set_add_ca(ctx):
2809 ctx.set_client_ca_list([cadesc, sedesc])
2810 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002811 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002812 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002813
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002814
2815 def test_set_after_add_client_ca(self):
2816 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002817 A call to :py:obj:`Context.set_client_ca_list` after a call to
2818 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002819 call with the names specified by the latter cal.
2820 """
2821 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2822 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2823 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2824
2825 cadesc = cacert.get_subject()
2826 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002827
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002828 def set_replaces_add_ca(ctx):
2829 ctx.add_client_ca(clcert)
2830 ctx.set_client_ca_list([cadesc])
2831 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002832 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002833 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002834
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002835
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002836
2837class ConnectionBIOTests(TestCase):
2838 """
2839 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
2840 """
2841 def test_wantReadError(self):
2842 """
2843 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
2844 if there are no bytes available to be read from the BIO.
2845 """
2846 ctx = Context(TLSv1_METHOD)
2847 conn = Connection(ctx, None)
2848 self.assertRaises(WantReadError, conn.bio_read, 1024)
2849
2850
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002851 def test_buffer_size(self):
2852 """
2853 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
2854 number of bytes to read and return.
2855 """
2856 ctx = Context(TLSv1_METHOD)
2857 conn = Connection(ctx, None)
2858 conn.set_connect_state()
2859 try:
2860 conn.do_handshake()
2861 except WantReadError:
2862 pass
2863 data = conn.bio_read(2)
2864 self.assertEqual(2, len(data))
2865
2866
2867 if not PY3:
2868 def test_buffer_size_long(self):
2869 """
2870 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
2871 :py:obj:`long` as well as :py:obj:`int`.
2872 """
2873 ctx = Context(TLSv1_METHOD)
2874 conn = Connection(ctx, None)
2875 conn.set_connect_state()
2876 try:
2877 conn.do_handshake()
2878 except WantReadError:
2879 pass
2880 data = conn.bio_read(long(2))
2881 self.assertEqual(2, len(data))
2882
2883
2884
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002885
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04002886class InfoConstantTests(TestCase):
2887 """
2888 Tests for assorted constants exposed for use in info callbacks.
2889 """
2890 def test_integers(self):
2891 """
2892 All of the info constants are integers.
2893
2894 This is a very weak test. It would be nice to have one that actually
2895 verifies that as certain info events happen, the value passed to the
2896 info callback matches up with the constant exposed by OpenSSL.SSL.
2897 """
2898 for const in [
2899 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
2900 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
2901 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
2902 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
2903 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
2904 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
2905
2906 self.assertTrue(isinstance(const, int))
2907
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02002908
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002909if __name__ == '__main__':
2910 main()