blob: fdeff9dfbf7d1138f0a04fadd923ffb988dc5827 [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 Calderoneb41d1f42014-04-17 16:02:04 -040024from OpenSSL.SSL import _lib
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040025from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
26from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040027from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040028from OpenSSL.SSL import (
29 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
30 TLSv1_1_METHOD, TLSv1_2_METHOD)
31from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040032from OpenSSL.SSL import (
33 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040034
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040035from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050036 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
37 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
38 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
Andy Lutomirskif05a2732014-03-13 17:22:25 -070039from OpenSSL.SSL import (
Andy Lutomirski61d7d392014-04-04 12:16:56 -070040 _Cryptography_HAS_EC, ELLIPTIC_CURVE_DESCRIPTIONS,
Jean-Paul Calderonec48cd812014-04-17 17:00:58 -040041 ECNotAvailable, UnknownObject, UnsupportedEllipticCurve)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050042
43from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070044 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050045from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070046 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040047
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050048from OpenSSL.test.util import TestCase, b
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040049from OpenSSL.test.test_crypto import (
50 cleartextCertificatePEM, cleartextPrivateKeyPEM)
51from OpenSSL.test.test_crypto import (
52 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
53 root_cert_pem)
54
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050055try:
56 from OpenSSL.SSL import OP_NO_QUERY_MTU
57except ImportError:
58 OP_NO_QUERY_MTU = None
59try:
60 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
61except ImportError:
62 OP_COOKIE_EXCHANGE = None
63try:
64 from OpenSSL.SSL import OP_NO_TICKET
65except ImportError:
66 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040067
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040068try:
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -040069 from OpenSSL.SSL import OP_NO_COMPRESSION
70except ImportError:
71 OP_NO_COMPRESSION = None
72
73try:
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040074 from OpenSSL.SSL import MODE_RELEASE_BUFFERS
75except ImportError:
76 MODE_RELEASE_BUFFERS = None
77
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040078try:
79 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
80except ImportError:
81 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
82
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040083from OpenSSL.SSL import (
84 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
85 SSL_ST_OK, SSL_ST_RENEGOTIATE,
86 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
87 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
88 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
89 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040090
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040091# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
92# to use)
93dhparam = """\
94-----BEGIN DH PARAMETERS-----
95MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
96-----END DH PARAMETERS-----
97"""
98
99
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400100def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400101 return ok
102
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400103
Rick Deanb1ccd562009-07-09 23:52:39 -0500104def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400105 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400106 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400107 """
108 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500109 port = socket()
110 port.bind(('', 0))
111 port.listen(1)
112 client = socket()
113 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400114 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400115 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500116 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500117
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400118 # Let's pass some unencrypted data to make sure our socket connection is
119 # fine. Just one byte, so we don't have to worry about buffers getting
120 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400121 server.send(b("x"))
122 assert client.recv(1024) == b("x")
123 client.send(b("y"))
124 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500125
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400126 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400127 server.setblocking(False)
128 client.setblocking(False)
129
Rick Deanb1ccd562009-07-09 23:52:39 -0500130 return (server, client)
131
132
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400133
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400134def handshake(client, server):
135 conns = [client, server]
136 while conns:
137 for conn in conns:
138 try:
139 conn.do_handshake()
140 except WantReadError:
141 pass
142 else:
143 conns.remove(conn)
144
145
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400146def _create_certificate_chain():
147 """
148 Construct and return a chain of certificates.
149
150 1. A new self-signed certificate authority certificate (cacert)
151 2. A new intermediate certificate signed by cacert (icert)
152 3. A new server certificate signed by icert (scert)
153 """
154 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
155
156 # Step 1
157 cakey = PKey()
158 cakey.generate_key(TYPE_RSA, 512)
159 cacert = X509()
160 cacert.get_subject().commonName = "Authority Certificate"
161 cacert.set_issuer(cacert.get_subject())
162 cacert.set_pubkey(cakey)
163 cacert.set_notBefore(b("20000101000000Z"))
164 cacert.set_notAfter(b("20200101000000Z"))
165 cacert.add_extensions([caext])
166 cacert.set_serial_number(0)
167 cacert.sign(cakey, "sha1")
168
169 # Step 2
170 ikey = PKey()
171 ikey.generate_key(TYPE_RSA, 512)
172 icert = X509()
173 icert.get_subject().commonName = "Intermediate Certificate"
174 icert.set_issuer(cacert.get_subject())
175 icert.set_pubkey(ikey)
176 icert.set_notBefore(b("20000101000000Z"))
177 icert.set_notAfter(b("20200101000000Z"))
178 icert.add_extensions([caext])
179 icert.set_serial_number(0)
180 icert.sign(cakey, "sha1")
181
182 # Step 3
183 skey = PKey()
184 skey.generate_key(TYPE_RSA, 512)
185 scert = X509()
186 scert.get_subject().commonName = "Server Certificate"
187 scert.set_issuer(icert.get_subject())
188 scert.set_pubkey(skey)
189 scert.set_notBefore(b("20000101000000Z"))
190 scert.set_notAfter(b("20200101000000Z"))
191 scert.add_extensions([
192 X509Extension(b('basicConstraints'), True, b('CA:false'))])
193 scert.set_serial_number(0)
194 scert.sign(ikey, "sha1")
195
196 return [(cakey, cacert), (ikey, icert), (skey, scert)]
197
198
199
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400200class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400201 """
202 Helper mixin which defines methods for creating a connected socket pair and
203 for forcing two connected SSL sockets to talk to each other via memory BIOs.
204 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500205 def _loopbackClientFactory(self, socket):
206 client = Connection(Context(TLSv1_METHOD), socket)
207 client.set_connect_state()
208 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400209
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500210
211 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400212 ctx = Context(TLSv1_METHOD)
213 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
214 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500215 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400216 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500217 return server
218
219
220 def _loopback(self, serverFactory=None, clientFactory=None):
221 if serverFactory is None:
222 serverFactory = self._loopbackServerFactory
223 if clientFactory is None:
224 clientFactory = self._loopbackClientFactory
225
226 (server, client) = socket_pair()
227 server = serverFactory(server)
228 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400229
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400230 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400231
232 server.setblocking(True)
233 client.setblocking(True)
234 return server, client
235
236
237 def _interactInMemory(self, client_conn, server_conn):
238 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900239 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400240 objects. Copy bytes back and forth between their send/receive buffers
241 for as long as there is anything to copy. When there is nothing more
Jonathan Ballet648875f2011-07-16 14:14:58 +0900242 to copy, return :py:obj:`None`. If one of them actually manages to deliver
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400243 some application bytes, return a two-tuple of the connection from which
244 the bytes were read and the bytes themselves.
245 """
246 wrote = True
247 while wrote:
248 # Loop until neither side has anything to say
249 wrote = False
250
251 # Copy stuff from each side's send buffer to the other side's
252 # receive buffer.
253 for (read, write) in [(client_conn, server_conn),
254 (server_conn, client_conn)]:
255
256 # Give the side a chance to generate some more bytes, or
257 # succeed.
258 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400259 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400260 except WantReadError:
261 # It didn't succeed, so we'll hope it generated some
262 # output.
263 pass
264 else:
265 # It did succeed, so we'll stop now and let the caller deal
266 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400267 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400268
269 while True:
270 # Keep copying as long as there's more stuff there.
271 try:
272 dirty = read.bio_read(4096)
273 except WantReadError:
274 # Okay, nothing more waiting to be sent. Stop
275 # processing this send buffer.
276 break
277 else:
278 # Keep track of the fact that someone generated some
279 # output.
280 wrote = True
281 write.bio_write(dirty)
282
283
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400284
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400285class VersionTests(TestCase):
286 """
287 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900288 :py:obj:`OpenSSL.SSL.SSLeay_version` and
289 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400290 """
291 def test_OPENSSL_VERSION_NUMBER(self):
292 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900293 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400294 byte and the patch, fix, minor, and major versions in the
295 nibbles above that.
296 """
297 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
298
299
300 def test_SSLeay_version(self):
301 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900302 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400303 one of a number of version strings based on that indicator.
304 """
305 versions = {}
306 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
307 SSLEAY_PLATFORM, SSLEAY_DIR]:
308 version = SSLeay_version(t)
309 versions[version] = t
310 self.assertTrue(isinstance(version, bytes))
311 self.assertEqual(len(versions), 5)
312
313
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400314
315class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400316 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900317 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400318 """
319 def test_method(self):
320 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900321 :py:obj:`Context` can be instantiated with one of :py:obj:`SSLv2_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400322 :py:obj:`SSLv3_METHOD`, :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
323 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400324 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400325 methods = [
326 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
327 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400328 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400329
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400330
331 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
332 for meth in maybe:
333 try:
334 Context(meth)
335 except (Error, ValueError):
336 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
337 # don't. Difficult to say in advance.
338 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400339
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400340 self.assertRaises(TypeError, Context, "")
341 self.assertRaises(ValueError, Context, 10)
342
343
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500344 if not PY3:
345 def test_method_long(self):
346 """
347 On Python 2 :py:class:`Context` accepts values of type
348 :py:obj:`long` as well as :py:obj:`int`.
349 """
350 Context(long(TLSv1_METHOD))
351
352
353
Rick Deane15b1472009-07-09 15:53:42 -0500354 def test_type(self):
355 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900356 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400357 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500358 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400359 self.assertIdentical(Context, ContextType)
360 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500361
362
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400363 def test_use_privatekey(self):
364 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900365 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400366 """
367 key = PKey()
368 key.generate_key(TYPE_RSA, 128)
369 ctx = Context(TLSv1_METHOD)
370 ctx.use_privatekey(key)
371 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400372
373
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800374 def test_use_privatekey_file_missing(self):
375 """
376 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error`
377 when passed the name of a file which does not exist.
378 """
379 ctx = Context(TLSv1_METHOD)
380 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
381
382
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500383 if not PY3:
384 def test_use_privatekey_file_long(self):
385 """
386 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
387 filetype of type :py:obj:`long` as well as :py:obj:`int`.
388 """
389 pemfile = self.mktemp()
390
391 key = PKey()
392 key.generate_key(TYPE_RSA, 128)
393
394 with open(pemfile, "wt") as pem:
395 pem.write(
396 dump_privatekey(FILETYPE_PEM, key).decode("ascii"))
397
398 ctx = Context(TLSv1_METHOD)
399 ctx.use_privatekey_file(pemfile, long(FILETYPE_PEM))
400
401
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800402 def test_use_certificate_wrong_args(self):
403 """
404 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
405 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as an
406 argument.
407 """
408 ctx = Context(TLSv1_METHOD)
409 self.assertRaises(TypeError, ctx.use_certificate)
410 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
411 self.assertRaises(TypeError, ctx.use_certificate, X509(), "hello, world")
412
413
414 def test_use_certificate_uninitialized(self):
415 """
416 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
417 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
418 initialized (ie, which does not actually have any certificate data).
419 """
420 ctx = Context(TLSv1_METHOD)
421 self.assertRaises(Error, ctx.use_certificate, X509())
422
423
424 def test_use_certificate(self):
425 """
426 :py:obj:`Context.use_certificate` sets the certificate which will be
427 used to identify connections created using the context.
428 """
429 # TODO
430 # Hard to assert anything. But we could set a privatekey then ask
431 # OpenSSL if the cert and key agree using check_privatekey. Then as
432 # long as check_privatekey works right we're good...
433 ctx = Context(TLSv1_METHOD)
434 ctx.use_certificate(load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
435
436
437 def test_use_certificate_file_wrong_args(self):
438 """
439 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
440 called with zero arguments or more than two arguments, or if the first
441 argument is not a byte string or the second argumnent is not an integer.
442 """
443 ctx = Context(TLSv1_METHOD)
444 self.assertRaises(TypeError, ctx.use_certificate_file)
445 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile", object())
446 self.assertRaises(
447 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM, object())
448 self.assertRaises(
449 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
450 self.assertRaises(
451 TypeError, ctx.use_certificate_file, b"somefile", object())
452
453
454 def test_use_certificate_file_missing(self):
455 """
456 :py:obj:`Context.use_certificate_file` raises
457 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does not
458 exist.
459 """
460 ctx = Context(TLSv1_METHOD)
461 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
462
463
464 def test_use_certificate_file(self):
465 """
466 :py:obj:`Context.use_certificate` sets the certificate which will be
467 used to identify connections created using the context.
468 """
469 # TODO
470 # Hard to assert anything. But we could set a privatekey then ask
471 # OpenSSL if the cert and key agree using check_privatekey. Then as
472 # long as check_privatekey works right we're good...
473 pem_filename = self.mktemp()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500474 with open(pem_filename, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800475 pem_file.write(cleartextCertificatePEM)
476
477 ctx = Context(TLSv1_METHOD)
478 ctx.use_certificate_file(pem_filename)
479
480
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500481 if not PY3:
482 def test_use_certificate_file_long(self):
483 """
484 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
485 filetype of type :py:obj:`long` as well as :py:obj:`int`.
486 """
487 pem_filename = self.mktemp()
488 with open(pem_filename, "wb") as pem_file:
489 pem_file.write(cleartextCertificatePEM)
490
491 ctx = Context(TLSv1_METHOD)
492 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
493
494
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400495 def test_set_app_data_wrong_args(self):
496 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900497 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called with other than
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400498 one argument.
499 """
500 context = Context(TLSv1_METHOD)
501 self.assertRaises(TypeError, context.set_app_data)
502 self.assertRaises(TypeError, context.set_app_data, None, None)
503
504
505 def test_get_app_data_wrong_args(self):
506 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900507 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400508 arguments.
509 """
510 context = Context(TLSv1_METHOD)
511 self.assertRaises(TypeError, context.get_app_data, None)
512
513
514 def test_app_data(self):
515 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900516 :py:obj:`Context.set_app_data` stores an object for later retrieval using
517 :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400518 """
519 app_data = object()
520 context = Context(TLSv1_METHOD)
521 context.set_app_data(app_data)
522 self.assertIdentical(context.get_app_data(), app_data)
523
524
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400525 def test_set_options_wrong_args(self):
526 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900527 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with the wrong
528 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400529 """
530 context = Context(TLSv1_METHOD)
531 self.assertRaises(TypeError, context.set_options)
532 self.assertRaises(TypeError, context.set_options, None)
533 self.assertRaises(TypeError, context.set_options, 1, None)
534
535
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500536 def test_set_options(self):
537 """
538 :py:obj:`Context.set_options` returns the new options value.
539 """
540 context = Context(TLSv1_METHOD)
541 options = context.set_options(OP_NO_SSLv2)
542 self.assertTrue(OP_NO_SSLv2 & options)
543
544
545 if not PY3:
546 def test_set_options_long(self):
547 """
548 On Python 2 :py:obj:`Context.set_options` accepts values of type
549 :py:obj:`long` as well as :py:obj:`int`.
550 """
551 context = Context(TLSv1_METHOD)
552 options = context.set_options(long(OP_NO_SSLv2))
553 self.assertTrue(OP_NO_SSLv2 & options)
554
555
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300556 def test_set_mode_wrong_args(self):
557 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400558 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with the wrong
559 number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300560 """
561 context = Context(TLSv1_METHOD)
562 self.assertRaises(TypeError, context.set_mode)
563 self.assertRaises(TypeError, context.set_mode, None)
564 self.assertRaises(TypeError, context.set_mode, 1, None)
565
566
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400567 if MODE_RELEASE_BUFFERS is not None:
568 def test_set_mode(self):
569 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400570 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the newly
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400571 set mode.
572 """
573 context = Context(TLSv1_METHOD)
574 self.assertTrue(
575 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500576
577 if not PY3:
578 def test_set_mode_long(self):
579 """
580 On Python 2 :py:obj:`Context.set_mode` accepts values of type
581 :py:obj:`long` as well as :py:obj:`int`.
582 """
583 context = Context(TLSv1_METHOD)
584 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
585 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400586 else:
587 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
588
589
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400590 def test_set_timeout_wrong_args(self):
591 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900592 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with the wrong
593 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400594 """
595 context = Context(TLSv1_METHOD)
596 self.assertRaises(TypeError, context.set_timeout)
597 self.assertRaises(TypeError, context.set_timeout, None)
598 self.assertRaises(TypeError, context.set_timeout, 1, None)
599
600
601 def test_get_timeout_wrong_args(self):
602 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900603 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400604 """
605 context = Context(TLSv1_METHOD)
606 self.assertRaises(TypeError, context.get_timeout, None)
607
608
609 def test_timeout(self):
610 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900611 :py:obj:`Context.set_timeout` sets the session timeout for all connections
612 created using the context object. :py:obj:`Context.get_timeout` retrieves this
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400613 value.
614 """
615 context = Context(TLSv1_METHOD)
616 context.set_timeout(1234)
617 self.assertEquals(context.get_timeout(), 1234)
618
619
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500620 if not PY3:
621 def test_timeout_long(self):
622 """
623 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
624 `long` as well as int.
625 """
626 context = Context(TLSv1_METHOD)
627 context.set_timeout(long(1234))
628 self.assertEquals(context.get_timeout(), 1234)
629
630
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400631 def test_set_verify_depth_wrong_args(self):
632 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900633 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called with the wrong
634 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400635 """
636 context = Context(TLSv1_METHOD)
637 self.assertRaises(TypeError, context.set_verify_depth)
638 self.assertRaises(TypeError, context.set_verify_depth, None)
639 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
640
641
642 def test_get_verify_depth_wrong_args(self):
643 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900644 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400645 """
646 context = Context(TLSv1_METHOD)
647 self.assertRaises(TypeError, context.get_verify_depth, None)
648
649
650 def test_verify_depth(self):
651 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900652 :py:obj:`Context.set_verify_depth` sets the number of certificates in a chain
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400653 to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900654 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400655 """
656 context = Context(TLSv1_METHOD)
657 context.set_verify_depth(11)
658 self.assertEquals(context.get_verify_depth(), 11)
659
660
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500661 if not PY3:
662 def test_verify_depth_long(self):
663 """
664 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
665 type `long` as well as int.
666 """
667 context = Context(TLSv1_METHOD)
668 context.set_verify_depth(long(11))
669 self.assertEquals(context.get_verify_depth(), 11)
670
671
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400672 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400673 """
674 Write a new private key out to a new file, encrypted using the given
675 passphrase. Return the path to the new file.
676 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400677 key = PKey()
678 key.generate_key(TYPE_RSA, 128)
679 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400680 fObj = open(pemFile, 'w')
681 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
682 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400683 fObj.close()
684 return pemFile
685
686
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400687 def test_set_passwd_cb_wrong_args(self):
688 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900689 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called with the
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400690 wrong arguments or with a non-callable first argument.
691 """
692 context = Context(TLSv1_METHOD)
693 self.assertRaises(TypeError, context.set_passwd_cb)
694 self.assertRaises(TypeError, context.set_passwd_cb, None)
695 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
696
697
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400698 def test_set_passwd_cb(self):
699 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900700 :py:obj:`Context.set_passwd_cb` accepts a callable which will be invoked when
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400701 a private key is loaded from an encrypted PEM.
702 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400703 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400704 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400705 calledWith = []
706 def passphraseCallback(maxlen, verify, extra):
707 calledWith.append((maxlen, verify, extra))
708 return passphrase
709 context = Context(TLSv1_METHOD)
710 context.set_passwd_cb(passphraseCallback)
711 context.use_privatekey_file(pemFile)
712 self.assertTrue(len(calledWith), 1)
713 self.assertTrue(isinstance(calledWith[0][0], int))
714 self.assertTrue(isinstance(calledWith[0][1], int))
715 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400716
717
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400718 def test_passwd_callback_exception(self):
719 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900720 :py:obj:`Context.use_privatekey_file` propagates any exception raised by the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400721 passphrase callback.
722 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400723 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400724 def passphraseCallback(maxlen, verify, extra):
725 raise RuntimeError("Sorry, I am a fail.")
726
727 context = Context(TLSv1_METHOD)
728 context.set_passwd_cb(passphraseCallback)
729 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
730
731
732 def test_passwd_callback_false(self):
733 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900734 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400735 passphrase callback returns a false value.
736 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400737 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400738 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500739 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400740
741 context = Context(TLSv1_METHOD)
742 context.set_passwd_cb(passphraseCallback)
743 self.assertRaises(Error, context.use_privatekey_file, pemFile)
744
745
746 def test_passwd_callback_non_string(self):
747 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900748 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400749 passphrase callback returns a true non-string value.
750 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400751 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400752 def passphraseCallback(maxlen, verify, extra):
753 return 10
754
755 context = Context(TLSv1_METHOD)
756 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800757 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400758
759
760 def test_passwd_callback_too_long(self):
761 """
762 If the passphrase returned by the passphrase callback returns a string
763 longer than the indicated maximum length, it is truncated.
764 """
765 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400766 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400767 pemFile = self._write_encrypted_pem(passphrase)
768 def passphraseCallback(maxlen, verify, extra):
769 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400770 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400771
772 context = Context(TLSv1_METHOD)
773 context.set_passwd_cb(passphraseCallback)
774 # This shall succeed because the truncated result is the correct
775 # passphrase.
776 context.use_privatekey_file(pemFile)
777
778
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400779 def test_set_info_callback(self):
780 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900781 :py:obj:`Context.set_info_callback` accepts a callable which will be invoked
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400782 when certain information about an SSL connection is available.
783 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500784 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400785
786 clientSSL = Connection(Context(TLSv1_METHOD), client)
787 clientSSL.set_connect_state()
788
789 called = []
790 def info(conn, where, ret):
791 called.append((conn, where, ret))
792 context = Context(TLSv1_METHOD)
793 context.set_info_callback(info)
794 context.use_certificate(
795 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
796 context.use_privatekey(
797 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
798
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400799 serverSSL = Connection(context, server)
800 serverSSL.set_accept_state()
801
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500802 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400803
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500804 # The callback must always be called with a Connection instance as the
805 # first argument. It would probably be better to split this into
806 # separate tests for client and server side info callbacks so we could
807 # assert it is called with the right Connection instance. It would
808 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500809 notConnections = [
810 conn for (conn, where, ret) in called
811 if not isinstance(conn, Connection)]
812 self.assertEqual(
813 [], notConnections,
814 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400815
816
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400817 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400818 """
819 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400820 its :py:obj:`load_verify_locations` method with the given arguments.
821 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400822 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500823 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400824
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400825 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400826 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400827 # Require that the server certificate verify properly or the
828 # connection will fail.
829 clientContext.set_verify(
830 VERIFY_PEER,
831 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
832
833 clientSSL = Connection(clientContext, client)
834 clientSSL.set_connect_state()
835
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400836 serverContext = Context(TLSv1_METHOD)
837 serverContext.use_certificate(
838 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
839 serverContext.use_privatekey(
840 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
841
842 serverSSL = Connection(serverContext, server)
843 serverSSL.set_accept_state()
844
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400845 # Without load_verify_locations above, the handshake
846 # will fail:
847 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
848 # 'certificate verify failed')]
849 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400850
851 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400852 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400853
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500854
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400855 def test_load_verify_file(self):
856 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900857 :py:obj:`Context.load_verify_locations` accepts a file name and uses the
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400858 certificates within for verification purposes.
859 """
860 cafile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400861 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400862 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400863 fObj.close()
864
865 self._load_verify_locations_test(cafile)
866
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400867
868 def test_load_verify_invalid_file(self):
869 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900870 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when passed a
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400871 non-existent cafile.
872 """
873 clientContext = Context(TLSv1_METHOD)
874 self.assertRaises(
875 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400876
877
878 def test_load_verify_directory(self):
879 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900880 :py:obj:`Context.load_verify_locations` accepts a directory name and uses
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400881 the certificates within for verification purposes.
882 """
883 capath = self.mktemp()
884 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400885 # Hash values computed manually with c_rehash to avoid depending on
886 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
887 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500888 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400889 cafile = join(capath, name)
890 fObj = open(cafile, 'w')
891 fObj.write(cleartextCertificatePEM.decode('ascii'))
892 fObj.close()
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400893
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400894 self._load_verify_locations_test(None, capath)
895
896
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400897 def test_load_verify_locations_wrong_args(self):
898 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900899 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if called with
900 the wrong number of arguments or with non-:py:obj:`str` arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400901 """
902 context = Context(TLSv1_METHOD)
903 self.assertRaises(TypeError, context.load_verify_locations)
904 self.assertRaises(TypeError, context.load_verify_locations, object())
905 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
906 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
907
908
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400909 if platform == "win32":
910 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400911 "See LP#404343 and LP#404344."
912 else:
913 def test_set_default_verify_paths(self):
914 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900915 :py:obj:`Context.set_default_verify_paths` causes the platform-specific CA
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400916 certificate locations to be used for verification purposes.
917 """
918 # Testing this requires a server with a certificate signed by one of
919 # the CAs in the platform CA location. Getting one of those costs
920 # money. Fortunately (or unfortunately, depending on your
921 # perspective), it's easy to think of a public server on the
922 # internet which has such a certificate. Connecting to the network
923 # in a unit test is bad, but it's the only way I can think of to
924 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400925
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400926 # Arg, verisign.com doesn't speak TLSv1
927 context = Context(SSLv3_METHOD)
928 context.set_default_verify_paths()
929 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +0200930 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400931 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400932
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400933 client = socket()
934 client.connect(('verisign.com', 443))
935 clientSSL = Connection(context, client)
936 clientSSL.set_connect_state()
937 clientSSL.do_handshake()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500938 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400939 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400940
941
942 def test_set_default_verify_paths_signature(self):
943 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900944 :py:obj:`Context.set_default_verify_paths` takes no arguments and raises
945 :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400946 """
947 context = Context(TLSv1_METHOD)
948 self.assertRaises(TypeError, context.set_default_verify_paths, None)
949 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
950 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500951
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400952
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500953 def test_add_extra_chain_cert_invalid_cert(self):
954 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900955 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if called with
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500956 other than one argument or if called with an object which is not an
Jonathan Ballet648875f2011-07-16 14:14:58 +0900957 instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500958 """
959 context = Context(TLSv1_METHOD)
960 self.assertRaises(TypeError, context.add_extra_chain_cert)
961 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
962 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
963
964
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400965 def _handshake_test(self, serverContext, clientContext):
966 """
967 Verify that a client and server created with the given contexts can
968 successfully handshake and communicate.
969 """
970 serverSocket, clientSocket = socket_pair()
971
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400972 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400973 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400974
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400975 client = Connection(clientContext, clientSocket)
976 client.set_connect_state()
977
978 # Make them talk to each other.
979 # self._interactInMemory(client, server)
980 for i in range(3):
981 for s in [client, server]:
982 try:
983 s.do_handshake()
984 except WantReadError:
985 pass
986
987
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800988 def test_set_verify_callback_exception(self):
989 """
990 If the verify callback passed to :py:obj:`Context.set_verify` raises an
991 exception, verification fails and the exception is propagated to the
992 caller of :py:obj:`Connection.do_handshake`.
993 """
994 serverContext = Context(TLSv1_METHOD)
995 serverContext.use_privatekey(
996 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
997 serverContext.use_certificate(
998 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
999
1000 clientContext = Context(TLSv1_METHOD)
1001 def verify_callback(*args):
1002 raise Exception("silly verify failure")
1003 clientContext.set_verify(VERIFY_PEER, verify_callback)
1004
1005 exc = self.assertRaises(
1006 Exception, self._handshake_test, serverContext, clientContext)
1007 self.assertEqual("silly verify failure", str(exc))
1008
1009
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001010 def test_add_extra_chain_cert(self):
1011 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001012 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509` instance to add to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001013 the certificate chain.
1014
Jonathan Ballet648875f2011-07-16 14:14:58 +09001015 See :py:obj:`_create_certificate_chain` for the details of the certificate
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001016 chain tested.
1017
1018 The chain is tested by starting a server with scert and connecting
1019 to it with a client which trusts cacert and requires verification to
1020 succeed.
1021 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001022 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001023 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1024
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001025 # Dump the CA certificate to a file because that's the only way to load
1026 # it as a trusted CA in the client context.
1027 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001028 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001029 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001030 fObj.close()
1031
1032 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001033 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001034 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001035 fObj.close()
1036
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001037 # Create the server context
1038 serverContext = Context(TLSv1_METHOD)
1039 serverContext.use_privatekey(skey)
1040 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001041 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001042 serverContext.add_extra_chain_cert(icert)
1043
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001044 # Create the client
1045 clientContext = Context(TLSv1_METHOD)
1046 clientContext.set_verify(
1047 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001048 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001049
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001050 # Try it out.
1051 self._handshake_test(serverContext, clientContext)
1052
1053
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001054 def test_use_certificate_chain_file(self):
1055 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001056 :py:obj:`Context.use_certificate_chain_file` reads a certificate chain from
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001057 the specified file.
1058
1059 The chain is tested by starting a server with scert and connecting
1060 to it with a client which trusts cacert and requires verification to
1061 succeed.
1062 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001063 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001064 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1065
1066 # Write out the chain file.
1067 chainFile = self.mktemp()
Jean-Paul Calderoned8607982014-01-18 10:30:55 -05001068 fObj = open(chainFile, 'wb')
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001069 # Most specific to least general.
Jean-Paul Calderoned8607982014-01-18 10:30:55 -05001070 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1071 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1072 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001073 fObj.close()
1074
1075 serverContext = Context(TLSv1_METHOD)
1076 serverContext.use_certificate_chain_file(chainFile)
1077 serverContext.use_privatekey(skey)
1078
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001079 fObj = open('ca.pem', 'w')
1080 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001081 fObj.close()
1082
1083 clientContext = Context(TLSv1_METHOD)
1084 clientContext.set_verify(
1085 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001086 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001087
1088 self._handshake_test(serverContext, clientContext)
1089
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001090
1091 def test_use_certificate_chain_file_wrong_args(self):
1092 """
1093 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1094 if passed zero or more than one argument or when passed a non-byte
1095 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error` when
1096 passed a bad chain file name (for example, the name of a file which does
1097 not exist).
1098 """
1099 context = Context(TLSv1_METHOD)
1100 self.assertRaises(TypeError, context.use_certificate_chain_file)
1101 self.assertRaises(TypeError, context.use_certificate_chain_file, object())
1102 self.assertRaises(TypeError, context.use_certificate_chain_file, b"foo", object())
1103
1104 self.assertRaises(Error, context.use_certificate_chain_file, self.mktemp())
1105
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001106 # XXX load_client_ca
1107 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001108
1109 def test_get_verify_mode_wrong_args(self):
1110 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001111 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001112 arguments.
1113 """
1114 context = Context(TLSv1_METHOD)
1115 self.assertRaises(TypeError, context.get_verify_mode, None)
1116
1117
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001118 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001119 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001120 :py:obj:`Context.get_verify_mode` returns the verify mode flags previously
1121 passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001122 """
1123 context = Context(TLSv1_METHOD)
1124 self.assertEquals(context.get_verify_mode(), 0)
1125 context.set_verify(
1126 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1127 self.assertEquals(
1128 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1129
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001130
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001131 if not PY3:
1132 def test_set_verify_mode_long(self):
1133 """
1134 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1135 type :py:obj:`long` as well as :py:obj:`int`.
1136 """
1137 context = Context(TLSv1_METHOD)
1138 self.assertEquals(context.get_verify_mode(), 0)
1139 context.set_verify(
1140 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None)
1141 self.assertEquals(
1142 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1143
1144
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001145 def test_load_tmp_dh_wrong_args(self):
1146 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001147 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
1148 number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001149 """
1150 context = Context(TLSv1_METHOD)
1151 self.assertRaises(TypeError, context.load_tmp_dh)
1152 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1153 self.assertRaises(TypeError, context.load_tmp_dh, object())
1154
1155
1156 def test_load_tmp_dh_missing_file(self):
1157 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001158 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the specified file
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001159 does not exist.
1160 """
1161 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001162 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001163
1164
1165 def test_load_tmp_dh(self):
1166 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001167 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001168 specified file.
1169 """
1170 context = Context(TLSv1_METHOD)
1171 dhfilename = self.mktemp()
1172 dhfile = open(dhfilename, "w")
1173 dhfile.write(dhparam)
1174 dhfile.close()
1175 context.load_tmp_dh(dhfilename)
1176 # XXX What should I assert here? -exarkun
1177
1178
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001179 def test_set_tmp_ecdh_curve(self):
1180 """
Jean-Paul Calderone3dfd4512014-04-17 16:02:19 -04001181 :py:obj:`Context.set_tmp_ecdh_curve` sets the elliptic curve for
1182 Diffie-Hellman to the specified named curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001183 """
1184 context = Context(TLSv1_METHOD)
1185 for curve in ELLIPTIC_CURVE_DESCRIPTIONS.keys():
1186 context.set_tmp_ecdh_curve(curve) # Must not throw.
1187
Laurens Van Houtvenf5df2432014-04-03 12:17:28 +02001188
Jean-Paul Calderoneb41d1f42014-04-17 16:02:04 -04001189 def test_set_tmp_ecdh_curve_not_available(self):
1190 """
1191 :py:obj:`Context.set_tmp_ecdh_curve` raises :py:obj:`ECNotAvailable` if
1192 elliptic curve support is not available from the underlying OpenSSL
1193 version at all.
1194 """
Jean-Paul Calderone689c4892014-04-17 16:42:49 -04001195 has_ec = _lib.Cryptography_HAS_EC
1196 try:
1197 _lib.Cryptography_HAS_EC = False
Jean-Paul Calderoneb41d1f42014-04-17 16:02:04 -04001198
Jean-Paul Calderone689c4892014-04-17 16:42:49 -04001199 context = Context(TLSv1_METHOD)
1200 self.assertRaises(
1201 ECNotAvailable,
1202 context.set_tmp_ecdh_curve, next(iter(ELLIPTIC_CURVE_DESCRIPTIONS)))
1203 finally:
1204 _lib.Cryptography_HAS_EC = has_ec
Jean-Paul Calderoneb41d1f42014-04-17 16:02:04 -04001205
1206
Jean-Paul Calderonec48cd812014-04-17 17:00:58 -04001207 def test_set_tmp_ecdh_curve_bad_curve_name(self):
Andy Lutomirski61d7d392014-04-04 12:16:56 -07001208 """
Jean-Paul Calderone3dfd4512014-04-17 16:02:19 -04001209 :py:obj:`Context.set_tmp_ecdh_curve` raises :py:obj:`UnknownObject` if
1210 passed a curve_name that OpenSSL does not recognize and EC is
1211 available.
Andy Lutomirski61d7d392014-04-04 12:16:56 -07001212 """
1213 context = Context(TLSv1_METHOD)
1214 try:
1215 context.set_tmp_ecdh_curve('not_an_elliptic_curve')
1216 except ECNotAvailable:
1217 self.assertFalse(_Cryptography_HAS_EC)
1218 except UnknownObject:
1219 self.assertTrue(_Cryptography_HAS_EC)
1220 else:
Jean-Paul Calderone5c7b52f2014-04-17 16:02:51 -04001221 self.fail(
1222 "set_tmp_ecdh_curve did not fail when called with "
1223 "non-existent curve name")
Andy Lutomirski61d7d392014-04-04 12:16:56 -07001224
1225
Jean-Paul Calderonec48cd812014-04-17 17:00:58 -04001226 def test_set_tmp_ecdh_curve_bad_nid(self):
1227 """
1228 :py:obj:`Context._set_tmp_ecdh_curve_by_nid`, an implementation detail
1229 of :py:obj:`Context.set_tmp_ecdh_curve`, raises
1230 :py:obj:`UnsupportedEllipticCurve` raises if passed a NID that does not
1231 identify a supported curve.
1232 """
1233 context = Context(TLSv1_METHOD)
1234 try:
1235 context._set_tmp_ecdh_curve_by_nid(
Jean-Paul Calderonecc30c932014-04-17 17:06:50 -04001236 u("curve"), _lib.OBJ_sn2nid(b"sha256"))
Jean-Paul Calderonec48cd812014-04-17 17:00:58 -04001237 except UnsupportedEllipticCurve:
1238 pass
1239 else:
1240 self.fail(
1241 "_set_tmp_ecdh_curve_by_nid did not raise "
1242 "UnsupportedEllipticCurve for a NID that does not "
1243 "identify a supported curve.")
1244
1245
Andy Lutomirski61d7d392014-04-04 12:16:56 -07001246 def test_set_tmp_ecdh_curve_not_a_curve(self):
1247 """
1248 :py:obj:`Context.set_tmp_ecdh_curve` raises
Jean-Paul Calderone3dfd4512014-04-17 16:02:19 -04001249 :py:obj:`UnsupportedEllipticCurve` if passed a curve_name that OpenSSL
1250 cannot instantiate as an elliptic curve. It raises
Andy Lutomirski61d7d392014-04-04 12:16:56 -07001251 :py:obj:`ECNotAvailable` if EC is not available at all.
1252 """
1253 context = Context(TLSv1_METHOD)
1254 try:
1255 context.set_tmp_ecdh_curve('sha256')
1256 except ECNotAvailable:
1257 self.assertFalse(_Cryptography_HAS_EC)
1258 except UnknownObject:
1259 self.assertTrue(_Cryptography_HAS_EC)
1260 else:
Jean-Paul Calderone5c7b52f2014-04-17 16:02:51 -04001261 self.fail(
1262 "set_tmp_ecdh_curve did not fail when called with "
1263 "a name that is not an elliptic curve")
Andy Lutomirski61d7d392014-04-04 12:16:56 -07001264
1265
Laurens Van Houtvenf5df2432014-04-03 12:17:28 +02001266 def test_has_curve_descriptions(self):
1267 """
1268 If the underlying cryptography bindings claim to have elliptic
1269 curve support, there should be at least one curve.
1270
1271 (In theory there could be an OpenSSL that violates this
1272 assumption. If so, this test will fail and we'll find out.)
1273
1274 """
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001275 if _Cryptography_HAS_EC:
Laurens Van Houtvenf5df2432014-04-03 12:17:28 +02001276 self.assertNotEqual(len(ELLIPTIC_CURVE_DESCRIPTIONS), 0)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001277
1278
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001279 def test_set_cipher_list_bytes(self):
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001280 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001281 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
1282 ciphers which connections created with the context object will be able
1283 to choose from.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001284 """
1285 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001286 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001287 conn = Connection(context, None)
1288 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001289
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001290
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001291 def test_set_cipher_list_text(self):
1292 """
1293 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
1294 the ciphers which connections created with the context object will be
1295 able to choose from.
1296 """
1297 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -05001298 context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001299 conn = Connection(context, None)
1300 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
1301
1302
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001303 def test_set_cipher_list_wrong_args(self):
1304 """
Jean-Paul Calderone17044832014-01-18 10:20:11 -05001305 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
1306 passed zero arguments or more than one argument or when passed a
1307 non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001308 passed an incorrect cipher list string.
1309 """
1310 context = Context(TLSv1_METHOD)
1311 self.assertRaises(TypeError, context.set_cipher_list)
1312 self.assertRaises(TypeError, context.set_cipher_list, object())
1313 self.assertRaises(TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object())
1314
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05001315 self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001316
1317
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001318 def test_set_session_cache_mode_wrong_args(self):
1319 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001320 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1321 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001322 """
1323 context = Context(TLSv1_METHOD)
1324 self.assertRaises(TypeError, context.set_session_cache_mode)
1325 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1326
1327
1328 def test_get_session_cache_mode_wrong_args(self):
1329 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001330 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1331 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001332 """
1333 context = Context(TLSv1_METHOD)
1334 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1335
1336
1337 def test_session_cache_mode(self):
1338 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001339 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1340 cached. The setting can be retrieved via
1341 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001342 """
1343 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001344 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001345 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1346 self.assertEqual(SESS_CACHE_OFF, off)
1347 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1348
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001349 if not PY3:
1350 def test_session_cache_mode_long(self):
1351 """
1352 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1353 of type :py:obj:`long` as well as :py:obj:`int`.
1354 """
1355 context = Context(TLSv1_METHOD)
1356 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1357 self.assertEqual(
1358 SESS_CACHE_BOTH, context.get_session_cache_mode())
1359
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001360
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001361 def test_get_cert_store(self):
1362 """
1363 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store` instance.
1364 """
1365 context = Context(TLSv1_METHOD)
1366 store = context.get_cert_store()
1367 self.assertIsInstance(store, X509Store)
1368
1369
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001370
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001371class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1372 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001373 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
1374 :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001375 """
1376 def test_wrong_args(self):
1377 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001378 :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001379 with other than one argument.
1380 """
1381 context = Context(TLSv1_METHOD)
1382 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1383 self.assertRaises(
1384 TypeError, context.set_tlsext_servername_callback, 1, 2)
1385
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001386
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001387 def test_old_callback_forgotten(self):
1388 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001389 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001390 callback, the one it replaces is dereferenced.
1391 """
1392 def callback(connection):
1393 pass
1394
1395 def replacement(connection):
1396 pass
1397
1398 context = Context(TLSv1_METHOD)
1399 context.set_tlsext_servername_callback(callback)
1400
1401 tracker = ref(callback)
1402 del callback
1403
1404 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001405
1406 # One run of the garbage collector happens to work on CPython. PyPy
1407 # doesn't collect the underlying object until a second run for whatever
1408 # reason. That's fine, it still demonstrates our code has properly
1409 # dropped the reference.
1410 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001411 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001412
1413 callback = tracker()
1414 if callback is not None:
1415 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001416 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001417 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001418
1419
1420 def test_no_servername(self):
1421 """
1422 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001423 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
1424 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001425 """
1426 args = []
1427 def servername(conn):
1428 args.append((conn, conn.get_servername()))
1429 context = Context(TLSv1_METHOD)
1430 context.set_tlsext_servername_callback(servername)
1431
1432 # Lose our reference to it. The Context is responsible for keeping it
1433 # alive now.
1434 del servername
1435 collect()
1436
1437 # Necessary to actually accept the connection
1438 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1439 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1440
1441 # Do a little connection to trigger the logic
1442 server = Connection(context, None)
1443 server.set_accept_state()
1444
1445 client = Connection(Context(TLSv1_METHOD), None)
1446 client.set_connect_state()
1447
1448 self._interactInMemory(server, client)
1449
1450 self.assertEqual([(server, None)], args)
1451
1452
1453 def test_servername(self):
1454 """
1455 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +09001456 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
1457 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001458 """
1459 args = []
1460 def servername(conn):
1461 args.append((conn, conn.get_servername()))
1462 context = Context(TLSv1_METHOD)
1463 context.set_tlsext_servername_callback(servername)
1464
1465 # Necessary to actually accept the connection
1466 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1467 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1468
1469 # Do a little connection to trigger the logic
1470 server = Connection(context, None)
1471 server.set_accept_state()
1472
1473 client = Connection(Context(TLSv1_METHOD), None)
1474 client.set_connect_state()
1475 client.set_tlsext_host_name(b("foo1.example.com"))
1476
1477 self._interactInMemory(server, client)
1478
1479 self.assertEqual([(server, b("foo1.example.com"))], args)
1480
1481
1482
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001483class SessionTests(TestCase):
1484 """
1485 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1486 """
1487 def test_construction(self):
1488 """
1489 :py:class:`Session` can be constructed with no arguments, creating a new
1490 instance of that type.
1491 """
1492 new_session = Session()
1493 self.assertTrue(isinstance(new_session, Session))
1494
1495
1496 def test_construction_wrong_args(self):
1497 """
1498 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
1499 is raised.
1500 """
1501 self.assertRaises(TypeError, Session, 123)
1502 self.assertRaises(TypeError, Session, "hello")
1503 self.assertRaises(TypeError, Session, object())
1504
1505
1506
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001507class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05001508 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001509 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001510 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001511 # XXX get_peer_certificate -> None
1512 # XXX sock_shutdown
1513 # XXX master_key -> TypeError
1514 # XXX server_random -> TypeError
1515 # XXX state_string
1516 # XXX connect -> TypeError
1517 # XXX connect_ex -> TypeError
1518 # XXX set_connect_state -> TypeError
1519 # XXX set_accept_state -> TypeError
1520 # XXX renegotiate_pending
1521 # XXX do_handshake -> TypeError
1522 # XXX bio_read -> TypeError
1523 # XXX recv -> TypeError
1524 # XXX send -> TypeError
1525 # XXX bio_write -> TypeError
1526
Rick Deane15b1472009-07-09 15:53:42 -05001527 def test_type(self):
1528 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001529 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001530 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05001531 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001532 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05001533 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001534 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05001535
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001536
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001537 def test_get_context(self):
1538 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001539 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
1540 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001541 """
1542 context = Context(TLSv1_METHOD)
1543 connection = Connection(context, None)
1544 self.assertIdentical(connection.get_context(), context)
1545
1546
1547 def test_get_context_wrong_args(self):
1548 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001549 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001550 arguments.
1551 """
1552 connection = Connection(Context(TLSv1_METHOD), None)
1553 self.assertRaises(TypeError, connection.get_context, None)
1554
1555
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001556 def test_set_context_wrong_args(self):
1557 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001558 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
1559 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001560 than 1.
1561 """
1562 ctx = Context(TLSv1_METHOD)
1563 connection = Connection(ctx, None)
1564 self.assertRaises(TypeError, connection.set_context)
1565 self.assertRaises(TypeError, connection.set_context, object())
1566 self.assertRaises(TypeError, connection.set_context, "hello")
1567 self.assertRaises(TypeError, connection.set_context, 1)
1568 self.assertRaises(TypeError, connection.set_context, 1, 2)
1569 self.assertRaises(
1570 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
1571 self.assertIdentical(ctx, connection.get_context())
1572
1573
1574 def test_set_context(self):
1575 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001576 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001577 for the connection.
1578 """
1579 original = Context(SSLv23_METHOD)
1580 replacement = Context(TLSv1_METHOD)
1581 connection = Connection(original, None)
1582 connection.set_context(replacement)
1583 self.assertIdentical(replacement, connection.get_context())
1584 # Lose our references to the contexts, just in case the Connection isn't
1585 # properly managing its own contributions to their reference counts.
1586 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001587 collect()
1588
1589
1590 def test_set_tlsext_host_name_wrong_args(self):
1591 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001592 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001593 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09001594 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001595 """
1596 conn = Connection(Context(TLSv1_METHOD), None)
1597 self.assertRaises(TypeError, conn.set_tlsext_host_name)
1598 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
1599 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
1600 self.assertRaises(
1601 TypeError, conn.set_tlsext_host_name, b("with\0null"))
1602
1603 if version_info >= (3,):
1604 # On Python 3.x, don't accidentally implicitly convert from text.
1605 self.assertRaises(
1606 TypeError,
1607 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001608
1609
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001610 def test_get_servername_wrong_args(self):
1611 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001612 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001613 arguments.
1614 """
1615 connection = Connection(Context(TLSv1_METHOD), None)
1616 self.assertRaises(TypeError, connection.get_servername, object())
1617 self.assertRaises(TypeError, connection.get_servername, 1)
1618 self.assertRaises(TypeError, connection.get_servername, "hello")
1619
1620
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001621 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001622 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001623 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001624 immediate read.
1625 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001626 connection = Connection(Context(TLSv1_METHOD), None)
1627 self.assertEquals(connection.pending(), 0)
1628
1629
1630 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001631 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001632 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001633 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001634 connection = Connection(Context(TLSv1_METHOD), None)
1635 self.assertRaises(TypeError, connection.pending, None)
1636
1637
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001638 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001639 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001640 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001641 argument or with the wrong number of arguments.
1642 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001643 connection = Connection(Context(TLSv1_METHOD), socket())
1644 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001645 self.assertRaises(TypeError, connection.connect)
1646 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001647
1648
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001649 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001650 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001651 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001652 connect method raises it.
1653 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001654 client = socket()
1655 context = Context(TLSv1_METHOD)
1656 clientSSL = Connection(context, client)
1657 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04001658 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001659
1660
1661 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001662 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001663 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001664 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001665 port = socket()
1666 port.bind(('', 0))
1667 port.listen(3)
1668
1669 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001670 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
1671 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001672
1673
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001674 if platform == "darwin":
1675 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
1676 else:
1677 def test_connect_ex(self):
1678 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001679 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001680 errno instead of raising an exception.
1681 """
1682 port = socket()
1683 port.bind(('', 0))
1684 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001685
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001686 clientSSL = Connection(Context(TLSv1_METHOD), socket())
1687 clientSSL.setblocking(False)
1688 result = clientSSL.connect_ex(port.getsockname())
1689 expected = (EINPROGRESS, EWOULDBLOCK)
1690 self.assertTrue(
1691 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001692
1693
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001694 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001695 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001696 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001697 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001698 connection = Connection(Context(TLSv1_METHOD), socket())
1699 self.assertRaises(TypeError, connection.accept, None)
1700
1701
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001702 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001703 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001704 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
1705 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001706 connection originated from.
1707 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001708 ctx = Context(TLSv1_METHOD)
1709 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1710 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001711 port = socket()
1712 portSSL = Connection(ctx, port)
1713 portSSL.bind(('', 0))
1714 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001715
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001716 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001717
1718 # Calling portSSL.getsockname() here to get the server IP address sounds
1719 # great, but frequently fails on Windows.
1720 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001721
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001722 serverSSL, address = portSSL.accept()
1723
1724 self.assertTrue(isinstance(serverSSL, Connection))
1725 self.assertIdentical(serverSSL.get_context(), ctx)
1726 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001727
1728
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001729 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001730 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001731 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001732 number of arguments or with arguments other than integers.
1733 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001734 connection = Connection(Context(TLSv1_METHOD), None)
1735 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04001736 self.assertRaises(TypeError, connection.get_shutdown, None)
1737 self.assertRaises(TypeError, connection.set_shutdown)
1738 self.assertRaises(TypeError, connection.set_shutdown, None)
1739 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001740
1741
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001742 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001743 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001744 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001745 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001746 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001747 self.assertFalse(server.shutdown())
1748 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001749 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001750 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
1751 client.shutdown()
1752 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
1753 self.assertRaises(ZeroReturnError, server.recv, 1024)
1754 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001755
1756
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001757 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001758 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001759 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001760 process.
1761 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001762 connection = Connection(Context(TLSv1_METHOD), socket())
1763 connection.set_shutdown(RECEIVED_SHUTDOWN)
1764 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1765
1766
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05001767 if not PY3:
1768 def test_set_shutdown_long(self):
1769 """
1770 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
1771 of type :py:obj:`long` as well as :py:obj:`int`.
1772 """
1773 connection = Connection(Context(TLSv1_METHOD), socket())
1774 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
1775 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1776
1777
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001778 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001779 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001780 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
1781 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001782 with any arguments.
1783 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001784 conn = Connection(Context(TLSv1_METHOD), None)
1785 self.assertRaises(TypeError, conn.get_app_data, None)
1786 self.assertRaises(TypeError, conn.set_app_data)
1787 self.assertRaises(TypeError, conn.set_app_data, None, None)
1788
1789
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001790 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001791 """
1792 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001793 :py:obj:`Connection.set_app_data` and later retrieved with
1794 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001795 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001796 conn = Connection(Context(TLSv1_METHOD), None)
1797 app_data = object()
1798 conn.set_app_data(app_data)
1799 self.assertIdentical(conn.get_app_data(), app_data)
1800
1801
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001802 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001803 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001804 :py:obj:`Connection.makefile` is not implemented and calling that method raises
1805 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001806 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001807 conn = Connection(Context(TLSv1_METHOD), None)
1808 self.assertRaises(NotImplementedError, conn.makefile)
1809
1810
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001811 def test_get_peer_cert_chain_wrong_args(self):
1812 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001813 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001814 arguments.
1815 """
1816 conn = Connection(Context(TLSv1_METHOD), None)
1817 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
1818 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
1819 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
1820 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
1821
1822
1823 def test_get_peer_cert_chain(self):
1824 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001825 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001826 the connected server returned for the certification verification.
1827 """
1828 chain = _create_certificate_chain()
1829 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1830
1831 serverContext = Context(TLSv1_METHOD)
1832 serverContext.use_privatekey(skey)
1833 serverContext.use_certificate(scert)
1834 serverContext.add_extra_chain_cert(icert)
1835 serverContext.add_extra_chain_cert(cacert)
1836 server = Connection(serverContext, None)
1837 server.set_accept_state()
1838
1839 # Create the client
1840 clientContext = Context(TLSv1_METHOD)
1841 clientContext.set_verify(VERIFY_NONE, verify_cb)
1842 client = Connection(clientContext, None)
1843 client.set_connect_state()
1844
1845 self._interactInMemory(client, server)
1846
1847 chain = client.get_peer_cert_chain()
1848 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001849 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001850 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001851 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001852 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001853 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001854 "Authority Certificate", chain[2].get_subject().CN)
1855
1856
1857 def test_get_peer_cert_chain_none(self):
1858 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001859 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001860 certificate chain.
1861 """
1862 ctx = Context(TLSv1_METHOD)
1863 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1864 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1865 server = Connection(ctx, None)
1866 server.set_accept_state()
1867 client = Connection(Context(TLSv1_METHOD), None)
1868 client.set_connect_state()
1869 self._interactInMemory(client, server)
1870 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001871
1872
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001873 def test_get_session_wrong_args(self):
1874 """
1875 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
1876 with any arguments.
1877 """
1878 ctx = Context(TLSv1_METHOD)
1879 server = Connection(ctx, None)
1880 self.assertRaises(TypeError, server.get_session, 123)
1881 self.assertRaises(TypeError, server.get_session, "hello")
1882 self.assertRaises(TypeError, server.get_session, object())
1883
1884
1885 def test_get_session_unconnected(self):
1886 """
1887 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
1888 an object which has not been connected.
1889 """
1890 ctx = Context(TLSv1_METHOD)
1891 server = Connection(ctx, None)
1892 session = server.get_session()
1893 self.assertIdentical(None, session)
1894
1895
1896 def test_server_get_session(self):
1897 """
1898 On the server side of a connection, :py:obj:`Connection.get_session`
1899 returns a :py:class:`Session` instance representing the SSL session for
1900 that connection.
1901 """
1902 server, client = self._loopback()
1903 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001904 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001905
1906
1907 def test_client_get_session(self):
1908 """
1909 On the client side of a connection, :py:obj:`Connection.get_session`
1910 returns a :py:class:`Session` instance representing the SSL session for
1911 that connection.
1912 """
1913 server, client = self._loopback()
1914 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001915 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001916
1917
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05001918 def test_set_session_wrong_args(self):
1919 """
1920 If called with an object that is not an instance of :py:class:`Session`,
1921 or with other than one argument, :py:obj:`Connection.set_session` raises
1922 :py:obj:`TypeError`.
1923 """
1924 ctx = Context(TLSv1_METHOD)
1925 connection = Connection(ctx, None)
1926 self.assertRaises(TypeError, connection.set_session)
1927 self.assertRaises(TypeError, connection.set_session, 123)
1928 self.assertRaises(TypeError, connection.set_session, "hello")
1929 self.assertRaises(TypeError, connection.set_session, object())
1930 self.assertRaises(
1931 TypeError, connection.set_session, Session(), Session())
1932
1933
1934 def test_client_set_session(self):
1935 """
1936 :py:obj:`Connection.set_session`, when used prior to a connection being
1937 established, accepts a :py:class:`Session` instance and causes an
1938 attempt to re-use the session it represents when the SSL handshake is
1939 performed.
1940 """
1941 key = load_privatekey(FILETYPE_PEM, server_key_pem)
1942 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
1943 ctx = Context(TLSv1_METHOD)
1944 ctx.use_privatekey(key)
1945 ctx.use_certificate(cert)
1946 ctx.set_session_id("unity-test")
1947
1948 def makeServer(socket):
1949 server = Connection(ctx, socket)
1950 server.set_accept_state()
1951 return server
1952
1953 originalServer, originalClient = self._loopback(
1954 serverFactory=makeServer)
1955 originalSession = originalClient.get_session()
1956
1957 def makeClient(socket):
1958 client = self._loopbackClientFactory(socket)
1959 client.set_session(originalSession)
1960 return client
1961 resumedServer, resumedClient = self._loopback(
1962 serverFactory=makeServer,
1963 clientFactory=makeClient)
1964
1965 # This is a proxy: in general, we have no access to any unique
1966 # identifier for the session (new enough versions of OpenSSL expose a
1967 # hash which could be usable, but "new enough" is very, very new).
1968 # Instead, exploit the fact that the master key is re-used if the
1969 # session is re-used. As long as the master key for the two connections
1970 # is the same, the session was re-used!
1971 self.assertEqual(
1972 originalServer.master_key(), resumedServer.master_key())
1973
1974
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05001975 def test_set_session_wrong_method(self):
1976 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05001977 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
1978 instance associated with a context using a different SSL method than the
1979 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
1980 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05001981 """
1982 key = load_privatekey(FILETYPE_PEM, server_key_pem)
1983 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
1984 ctx = Context(TLSv1_METHOD)
1985 ctx.use_privatekey(key)
1986 ctx.use_certificate(cert)
1987 ctx.set_session_id("unity-test")
1988
1989 def makeServer(socket):
1990 server = Connection(ctx, socket)
1991 server.set_accept_state()
1992 return server
1993
1994 originalServer, originalClient = self._loopback(
1995 serverFactory=makeServer)
1996 originalSession = originalClient.get_session()
1997
1998 def makeClient(socket):
1999 # Intentionally use a different, incompatible method here.
2000 client = Connection(Context(SSLv3_METHOD), socket)
2001 client.set_connect_state()
2002 client.set_session(originalSession)
2003 return client
2004
2005 self.assertRaises(
2006 Error,
2007 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2008
2009
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002010 def test_wantWriteError(self):
2011 """
2012 :py:obj:`Connection` methods which generate output raise
2013 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2014 fail indicating a should-write state.
2015 """
2016 client_socket, server_socket = socket_pair()
2017 # Fill up the client's send buffer so Connection won't be able to write
2018 # anything.
Jean-Paul Calderone7d7c9c22014-02-18 16:38:26 -05002019 msg = b"x" * 512
Jean-Paul Calderone22c28b42014-02-18 16:40:34 -05002020 for i in range(2048):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002021 try:
2022 client_socket.send(msg)
2023 except error as e:
2024 if e.errno == EWOULDBLOCK:
2025 break
2026 raise
2027 else:
2028 self.fail(
2029 "Failed to fill socket buffer, cannot test BIO want write")
2030
2031 ctx = Context(TLSv1_METHOD)
2032 conn = Connection(ctx, client_socket)
2033 # Client's speak first, so make it an SSL client
2034 conn.set_connect_state()
2035 self.assertRaises(WantWriteError, conn.do_handshake)
2036
2037 # XXX want_read
2038
Fedor Brunner416f4a12014-03-28 13:18:38 +01002039 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002040 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002041 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2042 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002043 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002044 ctx = Context(TLSv1_METHOD)
2045 connection = Connection(ctx, None)
2046 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002047
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002048
Fedor Brunner416f4a12014-03-28 13:18:38 +01002049 def test_get_peer_finished_before_connect(self):
2050 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002051 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2052 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002053 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002054 ctx = Context(TLSv1_METHOD)
2055 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002056 self.assertEqual(connection.get_peer_finished(), None)
2057
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002058
Fedor Brunner416f4a12014-03-28 13:18:38 +01002059 def test_get_finished(self):
2060 """
2061 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002062 message send from client, or server. Finished messages are send during
2063 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002064 """
2065
Fedor Brunner5747b932014-03-05 14:22:34 +01002066 server, client = self._loopback()
2067
2068 self.assertNotEqual(server.get_finished(), None)
2069 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002070
Jean-Paul Calderoned979f232014-03-30 11:58:00 -04002071
Fedor Brunner416f4a12014-03-28 13:18:38 +01002072 def test_get_peer_finished(self):
2073 """
2074 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002075 message received from client, or server. Finished messages are send
2076 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002077 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002078 server, client = self._loopback()
2079
2080 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002081 self.assertTrue(len(server.get_peer_finished()) > 0)
2082
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002083
Fedor Brunner416f4a12014-03-28 13:18:38 +01002084 def test_tls_finished_message_symmetry(self):
2085 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002086 The TLS Finished message send by server must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002087 received by client.
2088
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002089 The TLS Finished message send by client must be the TLS Finished message
Fedor Brunner416f4a12014-03-28 13:18:38 +01002090 received by server.
2091 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002092 server, client = self._loopback()
2093
Fedor Brunner5747b932014-03-05 14:22:34 +01002094 self.assertEqual(server.get_finished(), client.get_peer_finished())
2095 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002096
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002097
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002098 def test_get_cipher_name_before_connect(self):
2099 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002100 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2101 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002102 """
2103 ctx = Context(TLSv1_METHOD)
2104 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002105 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002106
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002107
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002108 def test_get_cipher_name(self):
2109 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002110 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2111 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002112 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002113 server, client = self._loopback()
2114 server_cipher_name, client_cipher_name = \
2115 server.get_cipher_name(), client.get_cipher_name()
2116
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002117 self.assertIsInstance(server_cipher_name, text_type)
2118 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002119
2120 self.assertEqual(server_cipher_name, client_cipher_name)
2121
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002122
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002123 def test_get_cipher_version_before_connect(self):
2124 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002125 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2126 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002127 """
2128 ctx = Context(TLSv1_METHOD)
2129 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002130 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002131
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002132
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002133 def test_get_cipher_version(self):
2134 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002135 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2136 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002137 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002138 server, client = self._loopback()
2139 server_cipher_version, client_cipher_version = \
2140 server.get_cipher_version(), client.get_cipher_version()
2141
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002142 self.assertIsInstance(server_cipher_version, text_type)
2143 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002144
2145 self.assertEqual(server_cipher_version, client_cipher_version)
2146
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002147
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002148 def test_get_cipher_bits_before_connect(self):
2149 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002150 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2151 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002152 """
2153 ctx = Context(TLSv1_METHOD)
2154 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002155 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002156
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002157
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002158 def test_get_cipher_bits(self):
2159 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002160 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2161 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002162 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002163 server, client = self._loopback()
2164 server_cipher_bits, client_cipher_bits = \
2165 server.get_cipher_bits(), client.get_cipher_bits()
2166
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002167 self.assertIsInstance(server_cipher_bits, int)
2168 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002169
2170 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002171
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002172
2173
2174class ConnectionGetCipherListTests(TestCase):
2175 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002176 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002177 """
2178 def test_wrong_args(self):
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002179 """
2180 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
2181 arguments.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002182 """
2183 connection = Connection(Context(TLSv1_METHOD), None)
2184 self.assertRaises(TypeError, connection.get_cipher_list, None)
2185
Jonathan Ballet648875f2011-07-16 14:14:58 +09002186
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002187 def test_result(self):
2188 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002189 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2190 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002191 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002192 connection = Connection(Context(TLSv1_METHOD), None)
2193 ciphers = connection.get_cipher_list()
2194 self.assertTrue(isinstance(ciphers, list))
2195 for cipher in ciphers:
2196 self.assertTrue(isinstance(cipher, str))
2197
2198
2199
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002200class ConnectionSendTests(TestCase, _LoopbackMixin):
2201 """
2202 Tests for :py:obj:`Connection.send`
2203 """
2204 def test_wrong_args(self):
2205 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002206 When called with arguments other than string argument for its first
2207 parameter or more than two arguments, :py:obj:`Connection.send` raises
2208 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002209 """
2210 connection = Connection(Context(TLSv1_METHOD), None)
2211 self.assertRaises(TypeError, connection.send)
2212 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002213 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002214
2215
2216 def test_short_bytes(self):
2217 """
2218 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
2219 and returns the number of bytes sent.
2220 """
2221 server, client = self._loopback()
2222 count = server.send(b('xy'))
2223 self.assertEquals(count, 2)
2224 self.assertEquals(client.recv(2), b('xy'))
2225
2226 try:
2227 memoryview
2228 except NameError:
2229 "cannot test sending memoryview without memoryview"
2230 else:
2231 def test_short_memoryview(self):
2232 """
2233 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002234 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002235 bytes sent.
2236 """
2237 server, client = self._loopback()
2238 count = server.send(memoryview(b('xy')))
2239 self.assertEquals(count, 2)
2240 self.assertEquals(client.recv(2), b('xy'))
2241
2242
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002243
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002244class ConnectionSendallTests(TestCase, _LoopbackMixin):
2245 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002246 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002247 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002248 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002249 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002250 When called with arguments other than a string argument for its first
2251 parameter or with more than two arguments, :py:obj:`Connection.sendall`
2252 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002253 """
2254 connection = Connection(Context(TLSv1_METHOD), None)
2255 self.assertRaises(TypeError, connection.sendall)
2256 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002257 self.assertRaises(
2258 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002259
2260
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002261 def test_short(self):
2262 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002263 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002264 it.
2265 """
2266 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04002267 server.sendall(b('x'))
2268 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002269
2270
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002271 try:
2272 memoryview
2273 except NameError:
2274 "cannot test sending memoryview without memoryview"
2275 else:
2276 def test_short_memoryview(self):
2277 """
2278 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002279 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002280 """
2281 server, client = self._loopback()
2282 server.sendall(memoryview(b('x')))
2283 self.assertEquals(client.recv(1), b('x'))
2284
2285
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002286 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002287 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002288 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002289 it even if this requires multiple calls of an underlying write function.
2290 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002291 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04002292 # Should be enough, underlying SSL_write should only do 16k at a time.
2293 # On Windows, after 32k of bytes the write will block (forever - because
2294 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04002295 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002296 server.sendall(message)
2297 accum = []
2298 received = 0
2299 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04002300 data = client.recv(1024)
2301 accum.append(data)
2302 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04002303 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002304
2305
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002306 def test_closed(self):
2307 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002308 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002309 write error from the low level write call.
2310 """
2311 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04002312 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002313 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02002314 if platform == "win32":
2315 self.assertEqual(exc.args[0], ESHUTDOWN)
2316 else:
2317 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002318
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002319
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002320
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002321class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
2322 """
2323 Tests for SSL renegotiation APIs.
2324 """
2325 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002326 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002327 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002328 arguments.
2329 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002330 connection = Connection(Context(TLSv1_METHOD), None)
2331 self.assertRaises(TypeError, connection.renegotiate, None)
2332
2333
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002334 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002335 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002336 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002337 any arguments.
2338 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002339 connection = Connection(Context(TLSv1_METHOD), None)
2340 self.assertRaises(TypeError, connection.total_renegotiations, None)
2341
2342
2343 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002344 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002345 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002346 renegotiations have happened.
2347 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002348 connection = Connection(Context(TLSv1_METHOD), None)
2349 self.assertEquals(connection.total_renegotiations(), 0)
2350
2351
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002352# def test_renegotiate(self):
2353# """
2354# """
2355# server, client = self._loopback()
2356
2357# server.send("hello world")
2358# self.assertEquals(client.recv(len("hello world")), "hello world")
2359
2360# self.assertEquals(server.total_renegotiations(), 0)
2361# self.assertTrue(server.renegotiate())
2362
2363# server.setblocking(False)
2364# client.setblocking(False)
2365# while server.renegotiate_pending():
2366# client.do_handshake()
2367# server.do_handshake()
2368
2369# self.assertEquals(server.total_renegotiations(), 1)
2370
2371
2372
2373
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002374class ErrorTests(TestCase):
2375 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002376 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002377 """
2378 def test_type(self):
2379 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002380 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002381 """
2382 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05002383 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05002384
2385
2386
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002387class ConstantsTests(TestCase):
2388 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002389 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002390
2391 These are values defined by OpenSSL intended only to be used as flags to
2392 OpenSSL APIs. The only assertions it seems can be made about them is
2393 their values.
2394 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002395 # unittest.TestCase has no skip mechanism
2396 if OP_NO_QUERY_MTU is not None:
2397 def test_op_no_query_mtu(self):
2398 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002399 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002400 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002401 """
2402 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
2403 else:
2404 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002405
2406
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002407 if OP_COOKIE_EXCHANGE is not None:
2408 def test_op_cookie_exchange(self):
2409 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002410 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002411 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002412 """
2413 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
2414 else:
2415 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002416
2417
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002418 if OP_NO_TICKET is not None:
2419 def test_op_no_ticket(self):
2420 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002421 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002422 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002423 """
2424 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04002425 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002426 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05002427
2428
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002429 if OP_NO_COMPRESSION is not None:
2430 def test_op_no_compression(self):
2431 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002432 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
2433 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002434 """
2435 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
2436 else:
2437 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
2438
2439
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002440 def test_sess_cache_off(self):
2441 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002442 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
2443 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002444 """
2445 self.assertEqual(0x0, SESS_CACHE_OFF)
2446
2447
2448 def test_sess_cache_client(self):
2449 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002450 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
2451 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002452 """
2453 self.assertEqual(0x1, SESS_CACHE_CLIENT)
2454
2455
2456 def test_sess_cache_server(self):
2457 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002458 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
2459 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002460 """
2461 self.assertEqual(0x2, SESS_CACHE_SERVER)
2462
2463
2464 def test_sess_cache_both(self):
2465 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002466 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
2467 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002468 """
2469 self.assertEqual(0x3, SESS_CACHE_BOTH)
2470
2471
2472 def test_sess_cache_no_auto_clear(self):
2473 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002474 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
2475 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
2476 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002477 """
2478 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
2479
2480
2481 def test_sess_cache_no_internal_lookup(self):
2482 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002483 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
2484 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
2485 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002486 """
2487 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
2488
2489
2490 def test_sess_cache_no_internal_store(self):
2491 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002492 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
2493 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
2494 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002495 """
2496 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
2497
2498
2499 def test_sess_cache_no_internal(self):
2500 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002501 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
2502 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
2503 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002504 """
2505 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
2506
2507
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04002508
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002509class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05002510 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002511 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05002512 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002513 def _server(self, sock):
2514 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002515 Create a new server-side SSL :py:obj:`Connection` object wrapped around
2516 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002517 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002518 # Create the server side Connection. This is mostly setup boilerplate
2519 # - use TLSv1, use a particular certificate, etc.
2520 server_ctx = Context(TLSv1_METHOD)
2521 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2522 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2523 server_store = server_ctx.get_cert_store()
2524 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2525 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2526 server_ctx.check_privatekey()
2527 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002528 # Here the Connection is actually created. If None is passed as the 2nd
2529 # parameter, it indicates a memory BIO should be created.
2530 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002531 server_conn.set_accept_state()
2532 return server_conn
2533
2534
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002535 def _client(self, sock):
2536 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002537 Create a new client-side SSL :py:obj:`Connection` object wrapped around
2538 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002539 """
2540 # Now create the client side Connection. Similar boilerplate to the
2541 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002542 client_ctx = Context(TLSv1_METHOD)
2543 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2544 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2545 client_store = client_ctx.get_cert_store()
2546 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
2547 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
2548 client_ctx.check_privatekey()
2549 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002550 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002551 client_conn.set_connect_state()
2552 return client_conn
2553
2554
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002555 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002556 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002557 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002558 reading from the output of each and writing those bytes to the input of
2559 the other and in this way establish a connection and exchange
2560 application-level bytes with each other.
2561 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002562 server_conn = self._server(None)
2563 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002564
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002565 # There should be no key or nonces yet.
2566 self.assertIdentical(server_conn.master_key(), None)
2567 self.assertIdentical(server_conn.client_random(), None)
2568 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002569
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002570 # First, the handshake needs to happen. We'll deliver bytes back and
2571 # forth between the client and server until neither of them feels like
2572 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002573 self.assertIdentical(
2574 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002575
2576 # Now that the handshake is done, there should be a key and nonces.
2577 self.assertNotIdentical(server_conn.master_key(), None)
2578 self.assertNotIdentical(server_conn.client_random(), None)
2579 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04002580 self.assertEquals(server_conn.client_random(), client_conn.client_random())
2581 self.assertEquals(server_conn.server_random(), client_conn.server_random())
2582 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
2583 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002584
2585 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002586 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05002587
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002588 server_conn.write(important_message)
2589 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002590 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002591 (client_conn, important_message))
2592
2593 client_conn.write(important_message[::-1])
2594 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002595 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002596 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05002597
2598
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002599 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05002600 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002601 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002602
2603 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09002604 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002605 this test fails, there must be a problem outside the memory BIO
2606 code, as no memory BIO is involved here). Even though this isn't a
2607 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05002608 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04002609 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05002610
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002611 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05002612 client_conn.send(important_message)
2613 msg = server_conn.recv(1024)
2614 self.assertEqual(msg, important_message)
2615
2616 # Again in the other direction, just for fun.
2617 important_message = important_message[::-1]
2618 server_conn.send(important_message)
2619 msg = client_conn.recv(1024)
2620 self.assertEqual(msg, important_message)
2621
2622
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04002623 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05002624 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002625 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
2626 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05002627 """
2628 context = Context(SSLv3_METHOD)
2629 client = socket()
2630 clientSSL = Connection(context, client)
2631 self.assertRaises( TypeError, clientSSL.bio_read, 100)
2632 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04002633 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002634
2635
2636 def test_outgoingOverflow(self):
2637 """
2638 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002639 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002640 returned and that many bytes from the beginning of the input can be
2641 read from the other end of the connection.
2642 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002643 server = self._server(None)
2644 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002645
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002646 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002647
2648 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002649 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002650 # Sanity check. We're trying to test what happens when the entire
2651 # input can't be sent. If the entire input was sent, this test is
2652 # meaningless.
2653 self.assertTrue(sent < size)
2654
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002655 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002656 self.assertIdentical(receiver, server)
2657
2658 # We can rely on all of these bytes being received at once because
2659 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
2660 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002661
2662
2663 def test_shutdown(self):
2664 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002665 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
2666 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002667 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002668 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002669 server.bio_shutdown()
2670 e = self.assertRaises(Error, server.recv, 1024)
2671 # We don't want WantReadError or ZeroReturnError or anything - it's a
2672 # handshake failure.
2673 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002674
2675
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002676 def test_unexpectedEndOfFile(self):
2677 """
2678 If the connection is lost before an orderly SSL shutdown occurs,
2679 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
2680 "Unexpected EOF".
2681 """
2682 server_conn, client_conn = self._loopback()
2683 client_conn.sock_shutdown(SHUT_RDWR)
2684 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
2685 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
2686
2687
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002688 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002689 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002690 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 -04002691
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002692 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002693 before the client and server are connected to each other. This
2694 function should specify a list of CAs for the server to send to the
2695 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09002696 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002697 times.
2698 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002699 server = self._server(None)
2700 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002701 self.assertEqual(client.get_client_ca_list(), [])
2702 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002703 ctx = server.get_context()
2704 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002705 self.assertEqual(client.get_client_ca_list(), [])
2706 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002707 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002708 self.assertEqual(client.get_client_ca_list(), expected)
2709 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002710
2711
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002712 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002713 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002714 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002715 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002716 """
2717 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002718 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
2719 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
2720 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002721
2722
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002723 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002724 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002725 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002726 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09002727 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002728 after the connection is set up.
2729 """
2730 def no_ca(ctx):
2731 ctx.set_client_ca_list([])
2732 return []
2733 self._check_client_ca_list(no_ca)
2734
2735
2736 def test_set_one_ca_list(self):
2737 """
2738 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002739 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002740 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002741 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002742 X509Name after the connection is set up.
2743 """
2744 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2745 cadesc = cacert.get_subject()
2746 def single_ca(ctx):
2747 ctx.set_client_ca_list([cadesc])
2748 return [cadesc]
2749 self._check_client_ca_list(single_ca)
2750
2751
2752 def test_set_multiple_ca_list(self):
2753 """
2754 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002755 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002756 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002757 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002758 X509Names after the connection is set up.
2759 """
2760 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2761 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2762
2763 sedesc = secert.get_subject()
2764 cldesc = clcert.get_subject()
2765
2766 def multiple_ca(ctx):
2767 L = [sedesc, cldesc]
2768 ctx.set_client_ca_list(L)
2769 return L
2770 self._check_client_ca_list(multiple_ca)
2771
2772
2773 def test_reset_ca_list(self):
2774 """
2775 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09002776 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002777 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002778 """
2779 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2780 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2781 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2782
2783 cadesc = cacert.get_subject()
2784 sedesc = secert.get_subject()
2785 cldesc = clcert.get_subject()
2786
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002787 def changed_ca(ctx):
2788 ctx.set_client_ca_list([sedesc, cldesc])
2789 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002790 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002791 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002792
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002793
2794 def test_mutated_ca_list(self):
2795 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002796 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002797 afterwards, this does not affect the list of CA names sent to the
2798 client.
2799 """
2800 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2801 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2802
2803 cadesc = cacert.get_subject()
2804 sedesc = secert.get_subject()
2805
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002806 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002807 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002808 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002809 L.append(sedesc)
2810 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002811 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002812
2813
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002814 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002815 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002816 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002817 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002818 """
2819 ctx = Context(TLSv1_METHOD)
2820 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002821 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002822 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002823 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002824
2825
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002826 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002827 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002828 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09002829 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002830 """
2831 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2832 cadesc = cacert.get_subject()
2833 def single_ca(ctx):
2834 ctx.add_client_ca(cacert)
2835 return [cadesc]
2836 self._check_client_ca_list(single_ca)
2837
2838
2839 def test_multiple_add_client_ca(self):
2840 """
2841 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09002842 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002843 """
2844 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2845 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2846
2847 cadesc = cacert.get_subject()
2848 sedesc = secert.get_subject()
2849
2850 def multiple_ca(ctx):
2851 ctx.add_client_ca(cacert)
2852 ctx.add_client_ca(secert)
2853 return [cadesc, sedesc]
2854 self._check_client_ca_list(multiple_ca)
2855
2856
2857 def test_set_and_add_client_ca(self):
2858 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002859 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
2860 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002861 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002862 """
2863 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2864 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2865 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2866
2867 cadesc = cacert.get_subject()
2868 sedesc = secert.get_subject()
2869 cldesc = clcert.get_subject()
2870
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002871 def mixed_set_add_ca(ctx):
2872 ctx.set_client_ca_list([cadesc, sedesc])
2873 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002874 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002875 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002876
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002877
2878 def test_set_after_add_client_ca(self):
2879 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002880 A call to :py:obj:`Context.set_client_ca_list` after a call to
2881 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002882 call with the names specified by the latter cal.
2883 """
2884 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2885 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2886 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2887
2888 cadesc = cacert.get_subject()
2889 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002890
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002891 def set_replaces_add_ca(ctx):
2892 ctx.add_client_ca(clcert)
2893 ctx.set_client_ca_list([cadesc])
2894 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002895 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002896 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002897
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002898
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002899
2900class ConnectionBIOTests(TestCase):
2901 """
2902 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
2903 """
2904 def test_wantReadError(self):
2905 """
2906 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
2907 if there are no bytes available to be read from the BIO.
2908 """
2909 ctx = Context(TLSv1_METHOD)
2910 conn = Connection(ctx, None)
2911 self.assertRaises(WantReadError, conn.bio_read, 1024)
2912
2913
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002914 def test_buffer_size(self):
2915 """
2916 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
2917 number of bytes to read and return.
2918 """
2919 ctx = Context(TLSv1_METHOD)
2920 conn = Connection(ctx, None)
2921 conn.set_connect_state()
2922 try:
2923 conn.do_handshake()
2924 except WantReadError:
2925 pass
2926 data = conn.bio_read(2)
2927 self.assertEqual(2, len(data))
2928
2929
2930 if not PY3:
2931 def test_buffer_size_long(self):
2932 """
2933 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
2934 :py:obj:`long` as well as :py:obj:`int`.
2935 """
2936 ctx = Context(TLSv1_METHOD)
2937 conn = Connection(ctx, None)
2938 conn.set_connect_state()
2939 try:
2940 conn.do_handshake()
2941 except WantReadError:
2942 pass
2943 data = conn.bio_read(long(2))
2944 self.assertEqual(2, len(data))
2945
2946
2947
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002948
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04002949class InfoConstantTests(TestCase):
2950 """
2951 Tests for assorted constants exposed for use in info callbacks.
2952 """
2953 def test_integers(self):
2954 """
2955 All of the info constants are integers.
2956
2957 This is a very weak test. It would be nice to have one that actually
2958 verifies that as certain info events happen, the value passed to the
2959 info callback matches up with the constant exposed by OpenSSL.SSL.
2960 """
2961 for const in [
2962 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
2963 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
2964 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
2965 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
2966 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
2967 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
2968
2969 self.assertTrue(isinstance(const, int))
2970
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02002971
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002972if __name__ == '__main__':
2973 main()