blob: 2ab67fd1a7f30acec33940db1e3925ccd1f70e73 [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"""
5Unit tests for L{OpenSSL.SSL}.
6"""
7
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04008from gc import collect
Jean-Paul Calderone8322d782010-09-17 19:22:31 -04009from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040010from sys import platform, version_info
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -040011from socket import error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040012from os import makedirs
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -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 Calderone20222ae2011-05-19 21:43:46 -040017from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040018from OpenSSL.crypto import PKey, X509, X509Extension
19from OpenSSL.crypto import dump_privatekey, load_privatekey
20from OpenSSL.crypto import dump_certificate, load_certificate
21
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040022from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
23from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040024from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040025from OpenSSL.SSL import SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD
Jean-Paul Calderone68649052009-07-17 21:14:27 -040026from OpenSSL.SSL import OP_NO_SSLv2, OP_NO_SSLv3, OP_SINGLE_DH_USE
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040027from OpenSSL.SSL import (
28 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
29from OpenSSL.SSL import (
30 Error, SysCallError, WantReadError, ZeroReturnError, SSLeay_version)
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040031from OpenSSL.SSL import Context, ContextType, Connection, ConnectionType
32
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -040033from OpenSSL.test.util import TestCase, bytes, b
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040034from OpenSSL.test.test_crypto import (
35 cleartextCertificatePEM, cleartextPrivateKeyPEM)
36from OpenSSL.test.test_crypto import (
37 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
38 root_cert_pem)
39
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050040try:
41 from OpenSSL.SSL import OP_NO_QUERY_MTU
42except ImportError:
43 OP_NO_QUERY_MTU = None
44try:
45 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
46except ImportError:
47 OP_COOKIE_EXCHANGE = None
48try:
49 from OpenSSL.SSL import OP_NO_TICKET
50except ImportError:
51 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040052
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040053from OpenSSL.SSL import (
54 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
55 SSL_ST_OK, SSL_ST_RENEGOTIATE,
56 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
57 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
58 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
59 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040060
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040061# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
62# to use)
63dhparam = """\
64-----BEGIN DH PARAMETERS-----
65MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
66-----END DH PARAMETERS-----
67"""
68
69
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040070def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040071 return ok
72
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040073
Rick Deanb1ccd562009-07-09 23:52:39 -050074def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040075 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -040076 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040077 """
78 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -050079 port = socket()
80 port.bind(('', 0))
81 port.listen(1)
82 client = socket()
83 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -040084 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -040085 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -050086 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -050087
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040088 # Let's pass some unencrypted data to make sure our socket connection is
89 # fine. Just one byte, so we don't have to worry about buffers getting
90 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -040091 server.send(b("x"))
92 assert client.recv(1024) == b("x")
93 client.send(b("y"))
94 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -050095
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -040096 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -040097 server.setblocking(False)
98 client.setblocking(False)
99
Rick Deanb1ccd562009-07-09 23:52:39 -0500100 return (server, client)
101
102
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400103
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400104def handshake(client, server):
105 conns = [client, server]
106 while conns:
107 for conn in conns:
108 try:
109 conn.do_handshake()
110 except WantReadError:
111 pass
112 else:
113 conns.remove(conn)
114
115
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400116def _create_certificate_chain():
117 """
118 Construct and return a chain of certificates.
119
120 1. A new self-signed certificate authority certificate (cacert)
121 2. A new intermediate certificate signed by cacert (icert)
122 3. A new server certificate signed by icert (scert)
123 """
124 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
125
126 # Step 1
127 cakey = PKey()
128 cakey.generate_key(TYPE_RSA, 512)
129 cacert = X509()
130 cacert.get_subject().commonName = "Authority Certificate"
131 cacert.set_issuer(cacert.get_subject())
132 cacert.set_pubkey(cakey)
133 cacert.set_notBefore(b("20000101000000Z"))
134 cacert.set_notAfter(b("20200101000000Z"))
135 cacert.add_extensions([caext])
136 cacert.set_serial_number(0)
137 cacert.sign(cakey, "sha1")
138
139 # Step 2
140 ikey = PKey()
141 ikey.generate_key(TYPE_RSA, 512)
142 icert = X509()
143 icert.get_subject().commonName = "Intermediate Certificate"
144 icert.set_issuer(cacert.get_subject())
145 icert.set_pubkey(ikey)
146 icert.set_notBefore(b("20000101000000Z"))
147 icert.set_notAfter(b("20200101000000Z"))
148 icert.add_extensions([caext])
149 icert.set_serial_number(0)
150 icert.sign(cakey, "sha1")
151
152 # Step 3
153 skey = PKey()
154 skey.generate_key(TYPE_RSA, 512)
155 scert = X509()
156 scert.get_subject().commonName = "Server Certificate"
157 scert.set_issuer(icert.get_subject())
158 scert.set_pubkey(skey)
159 scert.set_notBefore(b("20000101000000Z"))
160 scert.set_notAfter(b("20200101000000Z"))
161 scert.add_extensions([
162 X509Extension(b('basicConstraints'), True, b('CA:false'))])
163 scert.set_serial_number(0)
164 scert.sign(ikey, "sha1")
165
166 return [(cakey, cacert), (ikey, icert), (skey, scert)]
167
168
169
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400170class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400171 """
172 Helper mixin which defines methods for creating a connected socket pair and
173 for forcing two connected SSL sockets to talk to each other via memory BIOs.
174 """
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400175 def _loopback(self):
176 (server, client) = socket_pair()
177
178 ctx = Context(TLSv1_METHOD)
179 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
180 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
181 server = Connection(ctx, server)
182 server.set_accept_state()
183 client = Connection(Context(TLSv1_METHOD), client)
184 client.set_connect_state()
185
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400186 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400187
188 server.setblocking(True)
189 client.setblocking(True)
190 return server, client
191
192
193 def _interactInMemory(self, client_conn, server_conn):
194 """
195 Try to read application bytes from each of the two L{Connection}
196 objects. Copy bytes back and forth between their send/receive buffers
197 for as long as there is anything to copy. When there is nothing more
198 to copy, return C{None}. If one of them actually manages to deliver
199 some application bytes, return a two-tuple of the connection from which
200 the bytes were read and the bytes themselves.
201 """
202 wrote = True
203 while wrote:
204 # Loop until neither side has anything to say
205 wrote = False
206
207 # Copy stuff from each side's send buffer to the other side's
208 # receive buffer.
209 for (read, write) in [(client_conn, server_conn),
210 (server_conn, client_conn)]:
211
212 # Give the side a chance to generate some more bytes, or
213 # succeed.
214 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400215 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400216 except WantReadError:
217 # It didn't succeed, so we'll hope it generated some
218 # output.
219 pass
220 else:
221 # It did succeed, so we'll stop now and let the caller deal
222 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400223 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400224
225 while True:
226 # Keep copying as long as there's more stuff there.
227 try:
228 dirty = read.bio_read(4096)
229 except WantReadError:
230 # Okay, nothing more waiting to be sent. Stop
231 # processing this send buffer.
232 break
233 else:
234 # Keep track of the fact that someone generated some
235 # output.
236 wrote = True
237 write.bio_write(dirty)
238
239
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400240
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400241class VersionTests(TestCase):
242 """
243 Tests for version information exposed by
244 L{OpenSSL.SSL.SSLeay_version} and
245 L{OpenSSL.SSL.OPENSSL_VERSION_NUMBER}.
246 """
247 def test_OPENSSL_VERSION_NUMBER(self):
248 """
249 L{OPENSSL_VERSION_NUMBER} is an integer with status in the low
250 byte and the patch, fix, minor, and major versions in the
251 nibbles above that.
252 """
253 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
254
255
256 def test_SSLeay_version(self):
257 """
258 L{SSLeay_version} takes a version type indicator and returns
259 one of a number of version strings based on that indicator.
260 """
261 versions = {}
262 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
263 SSLEAY_PLATFORM, SSLEAY_DIR]:
264 version = SSLeay_version(t)
265 versions[version] = t
266 self.assertTrue(isinstance(version, bytes))
267 self.assertEqual(len(versions), 5)
268
269
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400270
271class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400272 """
273 Unit tests for L{OpenSSL.SSL.Context}.
274 """
275 def test_method(self):
276 """
277 L{Context} can be instantiated with one of L{SSLv2_METHOD},
278 L{SSLv3_METHOD}, L{SSLv23_METHOD}, or L{TLSv1_METHOD}.
279 """
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400280 for meth in [SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400281 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400282
283 try:
284 Context(SSLv2_METHOD)
285 except ValueError:
286 # Some versions of OpenSSL have SSLv2, some don't.
287 # Difficult to say in advance.
288 pass
289
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400290 self.assertRaises(TypeError, Context, "")
291 self.assertRaises(ValueError, Context, 10)
292
293
Rick Deane15b1472009-07-09 15:53:42 -0500294 def test_type(self):
295 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400296 L{Context} and L{ContextType} refer to the same type object and can be
297 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500298 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400299 self.assertIdentical(Context, ContextType)
300 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500301
302
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400303 def test_use_privatekey(self):
304 """
305 L{Context.use_privatekey} takes an L{OpenSSL.crypto.PKey} instance.
306 """
307 key = PKey()
308 key.generate_key(TYPE_RSA, 128)
309 ctx = Context(TLSv1_METHOD)
310 ctx.use_privatekey(key)
311 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400312
313
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400314 def test_set_app_data_wrong_args(self):
315 """
316 L{Context.set_app_data} raises L{TypeError} if called with other than
317 one argument.
318 """
319 context = Context(TLSv1_METHOD)
320 self.assertRaises(TypeError, context.set_app_data)
321 self.assertRaises(TypeError, context.set_app_data, None, None)
322
323
324 def test_get_app_data_wrong_args(self):
325 """
326 L{Context.get_app_data} raises L{TypeError} if called with any
327 arguments.
328 """
329 context = Context(TLSv1_METHOD)
330 self.assertRaises(TypeError, context.get_app_data, None)
331
332
333 def test_app_data(self):
334 """
335 L{Context.set_app_data} stores an object for later retrieval using
336 L{Context.get_app_data}.
337 """
338 app_data = object()
339 context = Context(TLSv1_METHOD)
340 context.set_app_data(app_data)
341 self.assertIdentical(context.get_app_data(), app_data)
342
343
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400344 def test_set_options_wrong_args(self):
345 """
346 L{Context.set_options} raises L{TypeError} if called with the wrong
347 number of arguments or a non-C{int} argument.
348 """
349 context = Context(TLSv1_METHOD)
350 self.assertRaises(TypeError, context.set_options)
351 self.assertRaises(TypeError, context.set_options, None)
352 self.assertRaises(TypeError, context.set_options, 1, None)
353
354
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400355 def test_set_timeout_wrong_args(self):
356 """
357 L{Context.set_timeout} raises L{TypeError} if called with the wrong
358 number of arguments or a non-C{int} argument.
359 """
360 context = Context(TLSv1_METHOD)
361 self.assertRaises(TypeError, context.set_timeout)
362 self.assertRaises(TypeError, context.set_timeout, None)
363 self.assertRaises(TypeError, context.set_timeout, 1, None)
364
365
366 def test_get_timeout_wrong_args(self):
367 """
368 L{Context.get_timeout} raises L{TypeError} if called with any arguments.
369 """
370 context = Context(TLSv1_METHOD)
371 self.assertRaises(TypeError, context.get_timeout, None)
372
373
374 def test_timeout(self):
375 """
376 L{Context.set_timeout} sets the session timeout for all connections
377 created using the context object. L{Context.get_timeout} retrieves this
378 value.
379 """
380 context = Context(TLSv1_METHOD)
381 context.set_timeout(1234)
382 self.assertEquals(context.get_timeout(), 1234)
383
384
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400385 def test_set_verify_depth_wrong_args(self):
386 """
387 L{Context.set_verify_depth} raises L{TypeError} if called with the wrong
388 number of arguments or a non-C{int} argument.
389 """
390 context = Context(TLSv1_METHOD)
391 self.assertRaises(TypeError, context.set_verify_depth)
392 self.assertRaises(TypeError, context.set_verify_depth, None)
393 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
394
395
396 def test_get_verify_depth_wrong_args(self):
397 """
398 L{Context.get_verify_depth} raises L{TypeError} if called with any arguments.
399 """
400 context = Context(TLSv1_METHOD)
401 self.assertRaises(TypeError, context.get_verify_depth, None)
402
403
404 def test_verify_depth(self):
405 """
406 L{Context.set_verify_depth} sets the number of certificates in a chain
407 to follow before giving up. The value can be retrieved with
408 L{Context.get_verify_depth}.
409 """
410 context = Context(TLSv1_METHOD)
411 context.set_verify_depth(11)
412 self.assertEquals(context.get_verify_depth(), 11)
413
414
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400415 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400416 """
417 Write a new private key out to a new file, encrypted using the given
418 passphrase. Return the path to the new file.
419 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400420 key = PKey()
421 key.generate_key(TYPE_RSA, 128)
422 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400423 fObj = open(pemFile, 'w')
424 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
425 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400426 fObj.close()
427 return pemFile
428
429
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400430 def test_set_passwd_cb_wrong_args(self):
431 """
432 L{Context.set_passwd_cb} raises L{TypeError} if called with the
433 wrong arguments or with a non-callable first argument.
434 """
435 context = Context(TLSv1_METHOD)
436 self.assertRaises(TypeError, context.set_passwd_cb)
437 self.assertRaises(TypeError, context.set_passwd_cb, None)
438 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
439
440
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400441 def test_set_passwd_cb(self):
442 """
443 L{Context.set_passwd_cb} accepts a callable which will be invoked when
444 a private key is loaded from an encrypted PEM.
445 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400446 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400447 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400448 calledWith = []
449 def passphraseCallback(maxlen, verify, extra):
450 calledWith.append((maxlen, verify, extra))
451 return passphrase
452 context = Context(TLSv1_METHOD)
453 context.set_passwd_cb(passphraseCallback)
454 context.use_privatekey_file(pemFile)
455 self.assertTrue(len(calledWith), 1)
456 self.assertTrue(isinstance(calledWith[0][0], int))
457 self.assertTrue(isinstance(calledWith[0][1], int))
458 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400459
460
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400461 def test_passwd_callback_exception(self):
462 """
463 L{Context.use_privatekey_file} propagates any exception raised by the
464 passphrase callback.
465 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400466 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400467 def passphraseCallback(maxlen, verify, extra):
468 raise RuntimeError("Sorry, I am a fail.")
469
470 context = Context(TLSv1_METHOD)
471 context.set_passwd_cb(passphraseCallback)
472 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
473
474
475 def test_passwd_callback_false(self):
476 """
477 L{Context.use_privatekey_file} raises L{OpenSSL.SSL.Error} if the
478 passphrase callback returns a false value.
479 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400480 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400481 def passphraseCallback(maxlen, verify, extra):
482 return None
483
484 context = Context(TLSv1_METHOD)
485 context.set_passwd_cb(passphraseCallback)
486 self.assertRaises(Error, context.use_privatekey_file, pemFile)
487
488
489 def test_passwd_callback_non_string(self):
490 """
491 L{Context.use_privatekey_file} raises L{OpenSSL.SSL.Error} if the
492 passphrase callback returns a true non-string value.
493 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400494 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400495 def passphraseCallback(maxlen, verify, extra):
496 return 10
497
498 context = Context(TLSv1_METHOD)
499 context.set_passwd_cb(passphraseCallback)
500 self.assertRaises(Error, context.use_privatekey_file, pemFile)
501
502
503 def test_passwd_callback_too_long(self):
504 """
505 If the passphrase returned by the passphrase callback returns a string
506 longer than the indicated maximum length, it is truncated.
507 """
508 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400509 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400510 pemFile = self._write_encrypted_pem(passphrase)
511 def passphraseCallback(maxlen, verify, extra):
512 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400513 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400514
515 context = Context(TLSv1_METHOD)
516 context.set_passwd_cb(passphraseCallback)
517 # This shall succeed because the truncated result is the correct
518 # passphrase.
519 context.use_privatekey_file(pemFile)
520
521
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400522 def test_set_info_callback(self):
523 """
524 L{Context.set_info_callback} accepts a callable which will be invoked
525 when certain information about an SSL connection is available.
526 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500527 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400528
529 clientSSL = Connection(Context(TLSv1_METHOD), client)
530 clientSSL.set_connect_state()
531
532 called = []
533 def info(conn, where, ret):
534 called.append((conn, where, ret))
535 context = Context(TLSv1_METHOD)
536 context.set_info_callback(info)
537 context.use_certificate(
538 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
539 context.use_privatekey(
540 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
541
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400542 serverSSL = Connection(context, server)
543 serverSSL.set_accept_state()
544
545 while not called:
546 for ssl in clientSSL, serverSSL:
547 try:
548 ssl.do_handshake()
549 except WantReadError:
550 pass
551
552 # Kind of lame. Just make sure it got called somehow.
553 self.assertTrue(called)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400554
555
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400556 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400557 """
558 Create a client context which will verify the peer certificate and call
559 its C{load_verify_locations} method with C{*args}. Then connect it to a
560 server and ensure that the handshake succeeds.
561 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500562 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400563
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400564 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400565 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400566 # Require that the server certificate verify properly or the
567 # connection will fail.
568 clientContext.set_verify(
569 VERIFY_PEER,
570 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
571
572 clientSSL = Connection(clientContext, client)
573 clientSSL.set_connect_state()
574
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400575 serverContext = Context(TLSv1_METHOD)
576 serverContext.use_certificate(
577 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
578 serverContext.use_privatekey(
579 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
580
581 serverSSL = Connection(serverContext, server)
582 serverSSL.set_accept_state()
583
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400584 # Without load_verify_locations above, the handshake
585 # will fail:
586 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
587 # 'certificate verify failed')]
588 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400589
590 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400591 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400592
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500593
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400594 def test_load_verify_file(self):
595 """
596 L{Context.load_verify_locations} accepts a file name and uses the
597 certificates within for verification purposes.
598 """
599 cafile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400600 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400601 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400602 fObj.close()
603
604 self._load_verify_locations_test(cafile)
605
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400606
607 def test_load_verify_invalid_file(self):
608 """
609 L{Context.load_verify_locations} raises L{Error} when passed a
610 non-existent cafile.
611 """
612 clientContext = Context(TLSv1_METHOD)
613 self.assertRaises(
614 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400615
616
617 def test_load_verify_directory(self):
618 """
619 L{Context.load_verify_locations} accepts a directory name and uses
620 the certificates within for verification purposes.
621 """
622 capath = self.mktemp()
623 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400624 # Hash values computed manually with c_rehash to avoid depending on
625 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
626 # from OpenSSL 1.0.0.
627 for name in ['c7adac82.0', 'c3705638.0']:
628 cafile = join(capath, name)
629 fObj = open(cafile, 'w')
630 fObj.write(cleartextCertificatePEM.decode('ascii'))
631 fObj.close()
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400632
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400633 self._load_verify_locations_test(None, capath)
634
635
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400636 def test_load_verify_locations_wrong_args(self):
637 """
638 L{Context.load_verify_locations} raises L{TypeError} if called with
639 the wrong number of arguments or with non-C{str} arguments.
640 """
641 context = Context(TLSv1_METHOD)
642 self.assertRaises(TypeError, context.load_verify_locations)
643 self.assertRaises(TypeError, context.load_verify_locations, object())
644 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
645 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
646
647
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400648 if platform == "win32":
649 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400650 "See LP#404343 and LP#404344."
651 else:
652 def test_set_default_verify_paths(self):
653 """
654 L{Context.set_default_verify_paths} causes the platform-specific CA
655 certificate locations to be used for verification purposes.
656 """
657 # Testing this requires a server with a certificate signed by one of
658 # the CAs in the platform CA location. Getting one of those costs
659 # money. Fortunately (or unfortunately, depending on your
660 # perspective), it's easy to think of a public server on the
661 # internet which has such a certificate. Connecting to the network
662 # in a unit test is bad, but it's the only way I can think of to
663 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400664
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400665 # Arg, verisign.com doesn't speak TLSv1
666 context = Context(SSLv3_METHOD)
667 context.set_default_verify_paths()
668 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +0200669 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400670 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400671
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400672 client = socket()
673 client.connect(('verisign.com', 443))
674 clientSSL = Connection(context, client)
675 clientSSL.set_connect_state()
676 clientSSL.do_handshake()
677 clientSSL.send('GET / HTTP/1.0\r\n\r\n')
678 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400679
680
681 def test_set_default_verify_paths_signature(self):
682 """
683 L{Context.set_default_verify_paths} takes no arguments and raises
684 L{TypeError} if given any.
685 """
686 context = Context(TLSv1_METHOD)
687 self.assertRaises(TypeError, context.set_default_verify_paths, None)
688 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
689 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500690
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400691
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500692 def test_add_extra_chain_cert_invalid_cert(self):
693 """
694 L{Context.add_extra_chain_cert} raises L{TypeError} if called with
695 other than one argument or if called with an object which is not an
696 instance of L{X509}.
697 """
698 context = Context(TLSv1_METHOD)
699 self.assertRaises(TypeError, context.add_extra_chain_cert)
700 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
701 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
702
703
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400704 def _handshake_test(self, serverContext, clientContext):
705 """
706 Verify that a client and server created with the given contexts can
707 successfully handshake and communicate.
708 """
709 serverSocket, clientSocket = socket_pair()
710
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400711 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400712 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400713
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400714 client = Connection(clientContext, clientSocket)
715 client.set_connect_state()
716
717 # Make them talk to each other.
718 # self._interactInMemory(client, server)
719 for i in range(3):
720 for s in [client, server]:
721 try:
722 s.do_handshake()
723 except WantReadError:
724 pass
725
726
727 def test_add_extra_chain_cert(self):
728 """
729 L{Context.add_extra_chain_cert} accepts an L{X509} instance to add to
730 the certificate chain.
731
732 See L{_create_certificate_chain} for the details of the certificate
733 chain tested.
734
735 The chain is tested by starting a server with scert and connecting
736 to it with a client which trusts cacert and requires verification to
737 succeed.
738 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400739 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400740 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
741
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400742 # Dump the CA certificate to a file because that's the only way to load
743 # it as a trusted CA in the client context.
744 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400745 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400746 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400747 fObj.close()
748
749 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400750 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400751 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400752 fObj.close()
753
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400754 # Create the server context
755 serverContext = Context(TLSv1_METHOD)
756 serverContext.use_privatekey(skey)
757 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400758 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400759 serverContext.add_extra_chain_cert(icert)
760
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400761 # Create the client
762 clientContext = Context(TLSv1_METHOD)
763 clientContext.set_verify(
764 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
765 clientContext.load_verify_locations('ca.pem')
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400766
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400767 # Try it out.
768 self._handshake_test(serverContext, clientContext)
769
770
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400771 def test_use_certificate_chain_file(self):
772 """
773 L{Context.use_certificate_chain_file} reads a certificate chain from
774 the specified file.
775
776 The chain is tested by starting a server with scert and connecting
777 to it with a client which trusts cacert and requires verification to
778 succeed.
779 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400780 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400781 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
782
783 # Write out the chain file.
784 chainFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400785 fObj = open(chainFile, 'w')
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400786 # Most specific to least general.
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400787 fObj.write(dump_certificate(FILETYPE_PEM, scert).decode('ascii'))
788 fObj.write(dump_certificate(FILETYPE_PEM, icert).decode('ascii'))
789 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400790 fObj.close()
791
792 serverContext = Context(TLSv1_METHOD)
793 serverContext.use_certificate_chain_file(chainFile)
794 serverContext.use_privatekey(skey)
795
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400796 fObj = open('ca.pem', 'w')
797 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400798 fObj.close()
799
800 clientContext = Context(TLSv1_METHOD)
801 clientContext.set_verify(
802 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
803 clientContext.load_verify_locations('ca.pem')
804
805 self._handshake_test(serverContext, clientContext)
806
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -0400807 # XXX load_client_ca
808 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -0400809
810 def test_get_verify_mode_wrong_args(self):
811 """
812 L{Context.get_verify_mode} raises L{TypeError} if called with any
813 arguments.
814 """
815 context = Context(TLSv1_METHOD)
816 self.assertRaises(TypeError, context.get_verify_mode, None)
817
818
819 def test_get_verify_mode(self):
820 """
821 L{Context.get_verify_mode} returns the verify mode flags previously
822 passed to L{Context.set_verify}.
823 """
824 context = Context(TLSv1_METHOD)
825 self.assertEquals(context.get_verify_mode(), 0)
826 context.set_verify(
827 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
828 self.assertEquals(
829 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
830
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400831
832 def test_load_tmp_dh_wrong_args(self):
833 """
834 L{Context.load_tmp_dh} raises L{TypeError} if called with the wrong
835 number of arguments or with a non-C{str} argument.
836 """
837 context = Context(TLSv1_METHOD)
838 self.assertRaises(TypeError, context.load_tmp_dh)
839 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
840 self.assertRaises(TypeError, context.load_tmp_dh, object())
841
842
843 def test_load_tmp_dh_missing_file(self):
844 """
845 L{Context.load_tmp_dh} raises L{OpenSSL.SSL.Error} if the specified file
846 does not exist.
847 """
848 context = Context(TLSv1_METHOD)
849 self.assertRaises(Error, context.load_tmp_dh, "hello")
850
851
852 def test_load_tmp_dh(self):
853 """
854 L{Context.load_tmp_dh} loads Diffie-Hellman parameters from the
855 specified file.
856 """
857 context = Context(TLSv1_METHOD)
858 dhfilename = self.mktemp()
859 dhfile = open(dhfilename, "w")
860 dhfile.write(dhparam)
861 dhfile.close()
862 context.load_tmp_dh(dhfilename)
863 # XXX What should I assert here? -exarkun
864
865
866 def test_set_cipher_list(self):
867 """
868 L{Context.set_cipher_list} accepts a C{str} naming the ciphers which
869 connections created with the context object will be able to choose from.
870 """
871 context = Context(TLSv1_METHOD)
872 context.set_cipher_list("hello world:EXP-RC4-MD5")
873 conn = Connection(context, None)
874 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400875
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400876
877
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -0400878class ServerNameCallbackTests(TestCase, _LoopbackMixin):
879 """
880 Tests for L{Context.set_tlsext_servername_callback} and its interaction with
881 L{Connection}.
882 """
883 def test_wrong_args(self):
884 """
885 L{Context.set_tlsext_servername_callback} raises L{TypeError} if called
886 with other than one argument.
887 """
888 context = Context(TLSv1_METHOD)
889 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
890 self.assertRaises(
891 TypeError, context.set_tlsext_servername_callback, 1, 2)
892
893 def test_old_callback_forgotten(self):
894 """
895 If L{Context.set_tlsext_servername_callback} is used to specify a new
896 callback, the one it replaces is dereferenced.
897 """
898 def callback(connection):
899 pass
900
901 def replacement(connection):
902 pass
903
904 context = Context(TLSv1_METHOD)
905 context.set_tlsext_servername_callback(callback)
906
907 tracker = ref(callback)
908 del callback
909
910 context.set_tlsext_servername_callback(replacement)
911 collect()
912 self.assertIdentical(None, tracker())
913
914
915 def test_no_servername(self):
916 """
917 When a client specifies no server name, the callback passed to
918 L{Context.set_tlsext_servername_callback} is invoked and the result of
919 L{Connection.get_servername} is C{None}.
920 """
921 args = []
922 def servername(conn):
923 args.append((conn, conn.get_servername()))
924 context = Context(TLSv1_METHOD)
925 context.set_tlsext_servername_callback(servername)
926
927 # Lose our reference to it. The Context is responsible for keeping it
928 # alive now.
929 del servername
930 collect()
931
932 # Necessary to actually accept the connection
933 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
934 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
935
936 # Do a little connection to trigger the logic
937 server = Connection(context, None)
938 server.set_accept_state()
939
940 client = Connection(Context(TLSv1_METHOD), None)
941 client.set_connect_state()
942
943 self._interactInMemory(server, client)
944
945 self.assertEqual([(server, None)], args)
946
947
948 def test_servername(self):
949 """
950 When a client specifies a server name in its hello message, the callback
951 passed to L{Contexts.set_tlsext_servername_callback} is invoked and the
952 result of L{Connection.get_servername} is that server name.
953 """
954 args = []
955 def servername(conn):
956 args.append((conn, conn.get_servername()))
957 context = Context(TLSv1_METHOD)
958 context.set_tlsext_servername_callback(servername)
959
960 # Necessary to actually accept the connection
961 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
962 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
963
964 # Do a little connection to trigger the logic
965 server = Connection(context, None)
966 server.set_accept_state()
967
968 client = Connection(Context(TLSv1_METHOD), None)
969 client.set_connect_state()
970 client.set_tlsext_host_name(b("foo1.example.com"))
971
972 self._interactInMemory(server, client)
973
974 self.assertEqual([(server, b("foo1.example.com"))], args)
975
976
977
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400978class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -0500979 """
980 Unit tests for L{OpenSSL.SSL.Connection}.
981 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -0400982 # XXX want_write
983 # XXX want_read
984 # XXX get_peer_certificate -> None
985 # XXX sock_shutdown
986 # XXX master_key -> TypeError
987 # XXX server_random -> TypeError
988 # XXX state_string
989 # XXX connect -> TypeError
990 # XXX connect_ex -> TypeError
991 # XXX set_connect_state -> TypeError
992 # XXX set_accept_state -> TypeError
993 # XXX renegotiate_pending
994 # XXX do_handshake -> TypeError
995 # XXX bio_read -> TypeError
996 # XXX recv -> TypeError
997 # XXX send -> TypeError
998 # XXX bio_write -> TypeError
999
Rick Deane15b1472009-07-09 15:53:42 -05001000 def test_type(self):
1001 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001002 L{Connection} and L{ConnectionType} refer to the same type object and
1003 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05001004 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001005 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05001006 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001007 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05001008
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001009
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001010 def test_get_context(self):
1011 """
1012 L{Connection.get_context} returns the L{Context} instance used to
1013 construct the L{Connection} instance.
1014 """
1015 context = Context(TLSv1_METHOD)
1016 connection = Connection(context, None)
1017 self.assertIdentical(connection.get_context(), context)
1018
1019
1020 def test_get_context_wrong_args(self):
1021 """
1022 L{Connection.get_context} raises L{TypeError} if called with any
1023 arguments.
1024 """
1025 connection = Connection(Context(TLSv1_METHOD), None)
1026 self.assertRaises(TypeError, connection.get_context, None)
1027
1028
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001029 def test_set_context_wrong_args(self):
1030 """
1031 L{Connection.set_context} raises L{TypeError} if called with a
1032 non-L{Context} instance argument or with any number of arguments other
1033 than 1.
1034 """
1035 ctx = Context(TLSv1_METHOD)
1036 connection = Connection(ctx, None)
1037 self.assertRaises(TypeError, connection.set_context)
1038 self.assertRaises(TypeError, connection.set_context, object())
1039 self.assertRaises(TypeError, connection.set_context, "hello")
1040 self.assertRaises(TypeError, connection.set_context, 1)
1041 self.assertRaises(TypeError, connection.set_context, 1, 2)
1042 self.assertRaises(
1043 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
1044 self.assertIdentical(ctx, connection.get_context())
1045
1046
1047 def test_set_context(self):
1048 """
1049 L{Connection.set_context} specifies a new L{Context} instance to be used
1050 for the connection.
1051 """
1052 original = Context(SSLv23_METHOD)
1053 replacement = Context(TLSv1_METHOD)
1054 connection = Connection(original, None)
1055 connection.set_context(replacement)
1056 self.assertIdentical(replacement, connection.get_context())
1057 # Lose our references to the contexts, just in case the Connection isn't
1058 # properly managing its own contributions to their reference counts.
1059 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001060 collect()
1061
1062
1063 def test_set_tlsext_host_name_wrong_args(self):
1064 """
1065 If L{Connection.set_tlsext_host_name} is called with a non-byte string
1066 argument or a byte string with an embedded NUL or other than one
1067 argument, L{TypeError} is raised.
1068 """
1069 conn = Connection(Context(TLSv1_METHOD), None)
1070 self.assertRaises(TypeError, conn.set_tlsext_host_name)
1071 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
1072 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
1073 self.assertRaises(
1074 TypeError, conn.set_tlsext_host_name, b("with\0null"))
1075
1076 if version_info >= (3,):
1077 # On Python 3.x, don't accidentally implicitly convert from text.
1078 self.assertRaises(
1079 TypeError,
1080 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001081
1082
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001083 def test_get_servername_wrong_args(self):
1084 """
1085 L{Connection.get_servername} raises L{TypeError} if called with any
1086 arguments.
1087 """
1088 connection = Connection(Context(TLSv1_METHOD), None)
1089 self.assertRaises(TypeError, connection.get_servername, object())
1090 self.assertRaises(TypeError, connection.get_servername, 1)
1091 self.assertRaises(TypeError, connection.get_servername, "hello")
1092
1093
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001094 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001095 """
1096 L{Connection.pending} returns the number of bytes available for
1097 immediate read.
1098 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001099 connection = Connection(Context(TLSv1_METHOD), None)
1100 self.assertEquals(connection.pending(), 0)
1101
1102
1103 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001104 """
1105 L{Connection.pending} raises L{TypeError} if called with any arguments.
1106 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001107 connection = Connection(Context(TLSv1_METHOD), None)
1108 self.assertRaises(TypeError, connection.pending, None)
1109
1110
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001111 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001112 """
1113 L{Connection.connect} raises L{TypeError} if called with a non-address
1114 argument or with the wrong number of arguments.
1115 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001116 connection = Connection(Context(TLSv1_METHOD), socket())
1117 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001118 self.assertRaises(TypeError, connection.connect)
1119 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001120
1121
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001122 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001123 """
1124 L{Connection.connect} raises L{socket.error} if the underlying socket
1125 connect method raises it.
1126 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001127 client = socket()
1128 context = Context(TLSv1_METHOD)
1129 clientSSL = Connection(context, client)
1130 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04001131 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001132
1133
1134 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001135 """
1136 L{Connection.connect} establishes a connection to the specified address.
1137 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001138 port = socket()
1139 port.bind(('', 0))
1140 port.listen(3)
1141
1142 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001143 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
1144 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001145
1146
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001147 if platform == "darwin":
1148 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
1149 else:
1150 def test_connect_ex(self):
1151 """
1152 If there is a connection error, L{Connection.connect_ex} returns the
1153 errno instead of raising an exception.
1154 """
1155 port = socket()
1156 port.bind(('', 0))
1157 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001158
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001159 clientSSL = Connection(Context(TLSv1_METHOD), socket())
1160 clientSSL.setblocking(False)
1161 result = clientSSL.connect_ex(port.getsockname())
1162 expected = (EINPROGRESS, EWOULDBLOCK)
1163 self.assertTrue(
1164 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001165
1166
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001167 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001168 """
1169 L{Connection.accept} raises L{TypeError} if called with any arguments.
1170 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001171 connection = Connection(Context(TLSv1_METHOD), socket())
1172 self.assertRaises(TypeError, connection.accept, None)
1173
1174
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001175 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001176 """
1177 L{Connection.accept} accepts a pending connection attempt and returns a
1178 tuple of a new L{Connection} (the accepted client) and the address the
1179 connection originated from.
1180 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001181 ctx = Context(TLSv1_METHOD)
1182 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1183 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001184 port = socket()
1185 portSSL = Connection(ctx, port)
1186 portSSL.bind(('', 0))
1187 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001188
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001189 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001190
1191 # Calling portSSL.getsockname() here to get the server IP address sounds
1192 # great, but frequently fails on Windows.
1193 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001194
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001195 serverSSL, address = portSSL.accept()
1196
1197 self.assertTrue(isinstance(serverSSL, Connection))
1198 self.assertIdentical(serverSSL.get_context(), ctx)
1199 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001200
1201
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001202 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001203 """
1204 L{Connection.shutdown} raises L{TypeError} if called with the wrong
1205 number of arguments or with arguments other than integers.
1206 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001207 connection = Connection(Context(TLSv1_METHOD), None)
1208 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04001209 self.assertRaises(TypeError, connection.get_shutdown, None)
1210 self.assertRaises(TypeError, connection.set_shutdown)
1211 self.assertRaises(TypeError, connection.set_shutdown, None)
1212 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001213
1214
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001215 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001216 """
1217 L{Connection.shutdown} performs an SSL-level connection shutdown.
1218 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001219 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001220 self.assertFalse(server.shutdown())
1221 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001222 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001223 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
1224 client.shutdown()
1225 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
1226 self.assertRaises(ZeroReturnError, server.recv, 1024)
1227 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001228
1229
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001230 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001231 """
1232 L{Connection.set_shutdown} sets the state of the SSL connection shutdown
1233 process.
1234 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001235 connection = Connection(Context(TLSv1_METHOD), socket())
1236 connection.set_shutdown(RECEIVED_SHUTDOWN)
1237 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1238
1239
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001240 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001241 """
1242 L{Connection.set_app_data} raises L{TypeError} if called with other than
1243 one argument. L{Connection.get_app_data} raises L{TypeError} if called
1244 with any arguments.
1245 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001246 conn = Connection(Context(TLSv1_METHOD), None)
1247 self.assertRaises(TypeError, conn.get_app_data, None)
1248 self.assertRaises(TypeError, conn.set_app_data)
1249 self.assertRaises(TypeError, conn.set_app_data, None, None)
1250
1251
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001252 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001253 """
1254 Any object can be set as app data by passing it to
1255 L{Connection.set_app_data} and later retrieved with
1256 L{Connection.get_app_data}.
1257 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001258 conn = Connection(Context(TLSv1_METHOD), None)
1259 app_data = object()
1260 conn.set_app_data(app_data)
1261 self.assertIdentical(conn.get_app_data(), app_data)
1262
1263
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001264 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001265 """
1266 L{Connection.makefile} is not implemented and calling that method raises
1267 L{NotImplementedError}.
1268 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001269 conn = Connection(Context(TLSv1_METHOD), None)
1270 self.assertRaises(NotImplementedError, conn.makefile)
1271
1272
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001273 def test_get_peer_cert_chain_wrong_args(self):
1274 """
1275 L{Connection.get_peer_cert_chain} raises L{TypeError} if called with any
1276 arguments.
1277 """
1278 conn = Connection(Context(TLSv1_METHOD), None)
1279 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
1280 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
1281 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
1282 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
1283
1284
1285 def test_get_peer_cert_chain(self):
1286 """
1287 L{Connection.get_peer_cert_chain} returns a list of certificates which
1288 the connected server returned for the certification verification.
1289 """
1290 chain = _create_certificate_chain()
1291 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1292
1293 serverContext = Context(TLSv1_METHOD)
1294 serverContext.use_privatekey(skey)
1295 serverContext.use_certificate(scert)
1296 serverContext.add_extra_chain_cert(icert)
1297 serverContext.add_extra_chain_cert(cacert)
1298 server = Connection(serverContext, None)
1299 server.set_accept_state()
1300
1301 # Create the client
1302 clientContext = Context(TLSv1_METHOD)
1303 clientContext.set_verify(VERIFY_NONE, verify_cb)
1304 client = Connection(clientContext, None)
1305 client.set_connect_state()
1306
1307 self._interactInMemory(client, server)
1308
1309 chain = client.get_peer_cert_chain()
1310 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001311 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001312 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001313 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001314 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001315 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001316 "Authority Certificate", chain[2].get_subject().CN)
1317
1318
1319 def test_get_peer_cert_chain_none(self):
1320 """
1321 L{Connection.get_peer_cert_chain} returns C{None} if the peer sends no
1322 certificate chain.
1323 """
1324 ctx = Context(TLSv1_METHOD)
1325 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1326 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1327 server = Connection(ctx, None)
1328 server.set_accept_state()
1329 client = Connection(Context(TLSv1_METHOD), None)
1330 client.set_connect_state()
1331 self._interactInMemory(client, server)
1332 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001333
1334
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001335
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001336class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001337 """
1338 Tests for L{Connection.get_cipher_list}.
1339 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04001340 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001341 """
1342 L{Connection.get_cipher_list} raises L{TypeError} if called with any
1343 arguments.
1344 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001345 connection = Connection(Context(TLSv1_METHOD), None)
1346 self.assertRaises(TypeError, connection.get_cipher_list, None)
1347
1348
1349 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001350 """
1351 L{Connection.get_cipher_list} returns a C{list} of C{str} giving the
1352 names of the ciphers which might be used.
1353 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001354 connection = Connection(Context(TLSv1_METHOD), None)
1355 ciphers = connection.get_cipher_list()
1356 self.assertTrue(isinstance(ciphers, list))
1357 for cipher in ciphers:
1358 self.assertTrue(isinstance(cipher, str))
1359
1360
1361
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001362class ConnectionSendTests(TestCase, _LoopbackMixin):
1363 """
1364 Tests for L{Connection.send}
1365 """
1366 def test_wrong_args(self):
1367 """
1368 When called with arguments other than a single string,
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05001369 L{Connection.send} raises L{TypeError}.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001370 """
1371 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05001372 self.assertRaises(TypeError, connection.send)
1373 self.assertRaises(TypeError, connection.send, object())
1374 self.assertRaises(TypeError, connection.send, "foo", "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001375
1376
1377 def test_short_bytes(self):
1378 """
1379 When passed a short byte string, L{Connection.send} transmits all of it
1380 and returns the number of bytes sent.
1381 """
1382 server, client = self._loopback()
1383 count = server.send(b('xy'))
1384 self.assertEquals(count, 2)
1385 self.assertEquals(client.recv(2), b('xy'))
1386
1387 try:
1388 memoryview
1389 except NameError:
1390 "cannot test sending memoryview without memoryview"
1391 else:
1392 def test_short_memoryview(self):
1393 """
1394 When passed a memoryview onto a small number of bytes,
1395 L{Connection.send} transmits all of them and returns the number of
1396 bytes sent.
1397 """
1398 server, client = self._loopback()
1399 count = server.send(memoryview(b('xy')))
1400 self.assertEquals(count, 2)
1401 self.assertEquals(client.recv(2), b('xy'))
1402
1403
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05001404
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001405class ConnectionSendallTests(TestCase, _LoopbackMixin):
1406 """
1407 Tests for L{Connection.sendall}.
1408 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001409 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001410 """
1411 When called with arguments other than a single string,
1412 L{Connection.sendall} raises L{TypeError}.
1413 """
1414 connection = Connection(Context(TLSv1_METHOD), None)
1415 self.assertRaises(TypeError, connection.sendall)
1416 self.assertRaises(TypeError, connection.sendall, object())
1417 self.assertRaises(TypeError, connection.sendall, "foo", "bar")
1418
1419
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001420 def test_short(self):
1421 """
1422 L{Connection.sendall} transmits all of the bytes in the string passed to
1423 it.
1424 """
1425 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001426 server.sendall(b('x'))
1427 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001428
1429
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05001430 try:
1431 memoryview
1432 except NameError:
1433 "cannot test sending memoryview without memoryview"
1434 else:
1435 def test_short_memoryview(self):
1436 """
1437 When passed a memoryview onto a small number of bytes,
1438 L{Connection.sendall} transmits all of them.
1439 """
1440 server, client = self._loopback()
1441 server.sendall(memoryview(b('x')))
1442 self.assertEquals(client.recv(1), b('x'))
1443
1444
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001445 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001446 """
1447 L{Connection.sendall} transmits all of the bytes in the string passed to
1448 it even if this requires multiple calls of an underlying write function.
1449 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001450 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04001451 # Should be enough, underlying SSL_write should only do 16k at a time.
1452 # On Windows, after 32k of bytes the write will block (forever - because
1453 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04001454 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001455 server.sendall(message)
1456 accum = []
1457 received = 0
1458 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001459 data = client.recv(1024)
1460 accum.append(data)
1461 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04001462 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001463
1464
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001465 def test_closed(self):
1466 """
1467 If the underlying socket is closed, L{Connection.sendall} propagates the
1468 write error from the low level write call.
1469 """
1470 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04001471 server.sock_shutdown(2)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001472 self.assertRaises(SysCallError, server.sendall, "hello, world")
1473
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001474
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001475
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001476class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
1477 """
1478 Tests for SSL renegotiation APIs.
1479 """
1480 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001481 """
1482 L{Connection.renegotiate} raises L{TypeError} if called with any
1483 arguments.
1484 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001485 connection = Connection(Context(TLSv1_METHOD), None)
1486 self.assertRaises(TypeError, connection.renegotiate, None)
1487
1488
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001489 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001490 """
1491 L{Connection.total_renegotiations} raises L{TypeError} if called with
1492 any arguments.
1493 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001494 connection = Connection(Context(TLSv1_METHOD), None)
1495 self.assertRaises(TypeError, connection.total_renegotiations, None)
1496
1497
1498 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001499 """
1500 L{Connection.total_renegotiations} returns C{0} before any
1501 renegotiations have happened.
1502 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001503 connection = Connection(Context(TLSv1_METHOD), None)
1504 self.assertEquals(connection.total_renegotiations(), 0)
1505
1506
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001507# def test_renegotiate(self):
1508# """
1509# """
1510# server, client = self._loopback()
1511
1512# server.send("hello world")
1513# self.assertEquals(client.recv(len("hello world")), "hello world")
1514
1515# self.assertEquals(server.total_renegotiations(), 0)
1516# self.assertTrue(server.renegotiate())
1517
1518# server.setblocking(False)
1519# client.setblocking(False)
1520# while server.renegotiate_pending():
1521# client.do_handshake()
1522# server.do_handshake()
1523
1524# self.assertEquals(server.total_renegotiations(), 1)
1525
1526
1527
1528
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001529class ErrorTests(TestCase):
1530 """
1531 Unit tests for L{OpenSSL.SSL.Error}.
1532 """
1533 def test_type(self):
1534 """
1535 L{Error} is an exception type.
1536 """
1537 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05001538 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05001539
1540
1541
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001542class ConstantsTests(TestCase):
1543 """
1544 Tests for the values of constants exposed in L{OpenSSL.SSL}.
1545
1546 These are values defined by OpenSSL intended only to be used as flags to
1547 OpenSSL APIs. The only assertions it seems can be made about them is
1548 their values.
1549 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001550 # unittest.TestCase has no skip mechanism
1551 if OP_NO_QUERY_MTU is not None:
1552 def test_op_no_query_mtu(self):
1553 """
1554 The value of L{OpenSSL.SSL.OP_NO_QUERY_MTU} is 0x1000, the value of
1555 I{SSL_OP_NO_QUERY_MTU} defined by I{openssl/ssl.h}.
1556 """
1557 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
1558 else:
1559 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001560
1561
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001562 if OP_COOKIE_EXCHANGE is not None:
1563 def test_op_cookie_exchange(self):
1564 """
1565 The value of L{OpenSSL.SSL.OP_COOKIE_EXCHANGE} is 0x2000, the value
1566 of I{SSL_OP_COOKIE_EXCHANGE} defined by I{openssl/ssl.h}.
1567 """
1568 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
1569 else:
1570 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001571
1572
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001573 if OP_NO_TICKET is not None:
1574 def test_op_no_ticket(self):
1575 """
1576 The value of L{OpenSSL.SSL.OP_NO_TICKET} is 0x4000, the value of
1577 I{SSL_OP_NO_TICKET} defined by I{openssl/ssl.h}.
1578 """
1579 self.assertEqual(OP_NO_TICKET, 0x4000)
1580 else:
1581 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05001582
1583
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04001584
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001585class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05001586 """
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001587 Tests for L{OpenSSL.SSL.Connection} using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05001588 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001589 def _server(self, sock):
1590 """
1591 Create a new server-side SSL L{Connection} object wrapped around
1592 C{sock}.
1593 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001594 # Create the server side Connection. This is mostly setup boilerplate
1595 # - use TLSv1, use a particular certificate, etc.
1596 server_ctx = Context(TLSv1_METHOD)
1597 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
1598 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
1599 server_store = server_ctx.get_cert_store()
1600 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1601 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1602 server_ctx.check_privatekey()
1603 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05001604 # Here the Connection is actually created. If None is passed as the 2nd
1605 # parameter, it indicates a memory BIO should be created.
1606 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001607 server_conn.set_accept_state()
1608 return server_conn
1609
1610
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001611 def _client(self, sock):
1612 """
1613 Create a new client-side SSL L{Connection} object wrapped around
1614 C{sock}.
1615 """
1616 # Now create the client side Connection. Similar boilerplate to the
1617 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001618 client_ctx = Context(TLSv1_METHOD)
1619 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
1620 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
1621 client_store = client_ctx.get_cert_store()
1622 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
1623 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
1624 client_ctx.check_privatekey()
1625 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05001626 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001627 client_conn.set_connect_state()
1628 return client_conn
1629
1630
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001631 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001632 """
1633 Two L{Connection}s which use memory BIOs can be manually connected by
1634 reading from the output of each and writing those bytes to the input of
1635 the other and in this way establish a connection and exchange
1636 application-level bytes with each other.
1637 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001638 server_conn = self._server(None)
1639 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05001640
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001641 # There should be no key or nonces yet.
1642 self.assertIdentical(server_conn.master_key(), None)
1643 self.assertIdentical(server_conn.client_random(), None)
1644 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05001645
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001646 # First, the handshake needs to happen. We'll deliver bytes back and
1647 # forth between the client and server until neither of them feels like
1648 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001649 self.assertIdentical(
1650 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001651
1652 # Now that the handshake is done, there should be a key and nonces.
1653 self.assertNotIdentical(server_conn.master_key(), None)
1654 self.assertNotIdentical(server_conn.client_random(), None)
1655 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04001656 self.assertEquals(server_conn.client_random(), client_conn.client_random())
1657 self.assertEquals(server_conn.server_random(), client_conn.server_random())
1658 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
1659 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001660
1661 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04001662 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05001663
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001664 server_conn.write(important_message)
1665 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001666 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001667 (client_conn, important_message))
1668
1669 client_conn.write(important_message[::-1])
1670 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001671 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001672 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05001673
1674
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001675 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05001676 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001677 Just like L{test_memoryConnect} but with an actual socket.
1678
1679 This is primarily to rule out the memory BIO code as the source of
1680 any problems encountered while passing data over a L{Connection} (if
1681 this test fails, there must be a problem outside the memory BIO
1682 code, as no memory BIO is involved here). Even though this isn't a
1683 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05001684 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04001685 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05001686
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04001687 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05001688 client_conn.send(important_message)
1689 msg = server_conn.recv(1024)
1690 self.assertEqual(msg, important_message)
1691
1692 # Again in the other direction, just for fun.
1693 important_message = important_message[::-1]
1694 server_conn.send(important_message)
1695 msg = client_conn.recv(1024)
1696 self.assertEqual(msg, important_message)
1697
1698
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04001699 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05001700 """
1701 Test that L{OpenSSL.SSL.bio_read} and L{OpenSSL.SSL.bio_write} don't
1702 work on L{OpenSSL.SSL.Connection}() that use sockets.
1703 """
1704 context = Context(SSLv3_METHOD)
1705 client = socket()
1706 clientSSL = Connection(context, client)
1707 self.assertRaises( TypeError, clientSSL.bio_read, 100)
1708 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04001709 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001710
1711
1712 def test_outgoingOverflow(self):
1713 """
1714 If more bytes than can be written to the memory BIO are passed to
1715 L{Connection.send} at once, the number of bytes which were written is
1716 returned and that many bytes from the beginning of the input can be
1717 read from the other end of the connection.
1718 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001719 server = self._server(None)
1720 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001721
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001722 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001723
1724 size = 2 ** 15
1725 sent = client.send("x" * size)
1726 # Sanity check. We're trying to test what happens when the entire
1727 # input can't be sent. If the entire input was sent, this test is
1728 # meaningless.
1729 self.assertTrue(sent < size)
1730
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001731 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001732 self.assertIdentical(receiver, server)
1733
1734 # We can rely on all of these bytes being received at once because
1735 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
1736 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04001737
1738
1739 def test_shutdown(self):
1740 """
1741 L{Connection.bio_shutdown} signals the end of the data stream from
1742 which the L{Connection} reads.
1743 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001744 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04001745 server.bio_shutdown()
1746 e = self.assertRaises(Error, server.recv, 1024)
1747 # We don't want WantReadError or ZeroReturnError or anything - it's a
1748 # handshake failure.
1749 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04001750
1751
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001752 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001753 """
1754 Verify the return value of the C{get_client_ca_list} method for server and client connections.
1755
1756 @param func: A function which will be called with the server context
1757 before the client and server are connected to each other. This
1758 function should specify a list of CAs for the server to send to the
1759 client and return that same list. The list will be used to verify
1760 that C{get_client_ca_list} returns the proper value at various
1761 times.
1762 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001763 server = self._server(None)
1764 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001765 self.assertEqual(client.get_client_ca_list(), [])
1766 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001767 ctx = server.get_context()
1768 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001769 self.assertEqual(client.get_client_ca_list(), [])
1770 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001771 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001772 self.assertEqual(client.get_client_ca_list(), expected)
1773 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001774
1775
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001776 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001777 """
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001778 L{Context.set_client_ca_list} raises a L{TypeError} if called with a
1779 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001780 """
1781 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001782 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
1783 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
1784 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001785
1786
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001787 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001788 """
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001789 If passed an empty list, L{Context.set_client_ca_list} configures the
1790 context to send no CA names to the client and, on both the server and
1791 client sides, L{Connection.get_client_ca_list} returns an empty list
1792 after the connection is set up.
1793 """
1794 def no_ca(ctx):
1795 ctx.set_client_ca_list([])
1796 return []
1797 self._check_client_ca_list(no_ca)
1798
1799
1800 def test_set_one_ca_list(self):
1801 """
1802 If passed a list containing a single X509Name,
1803 L{Context.set_client_ca_list} configures the context to send that CA
1804 name to the client and, on both the server and client sides,
1805 L{Connection.get_client_ca_list} returns a list containing that
1806 X509Name after the connection is set up.
1807 """
1808 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1809 cadesc = cacert.get_subject()
1810 def single_ca(ctx):
1811 ctx.set_client_ca_list([cadesc])
1812 return [cadesc]
1813 self._check_client_ca_list(single_ca)
1814
1815
1816 def test_set_multiple_ca_list(self):
1817 """
1818 If passed a list containing multiple X509Name objects,
1819 L{Context.set_client_ca_list} configures the context to send those CA
1820 names to the client and, on both the server and client sides,
1821 L{Connection.get_client_ca_list} returns a list containing those
1822 X509Names after the connection is set up.
1823 """
1824 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1825 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1826
1827 sedesc = secert.get_subject()
1828 cldesc = clcert.get_subject()
1829
1830 def multiple_ca(ctx):
1831 L = [sedesc, cldesc]
1832 ctx.set_client_ca_list(L)
1833 return L
1834 self._check_client_ca_list(multiple_ca)
1835
1836
1837 def test_reset_ca_list(self):
1838 """
1839 If called multiple times, only the X509Names passed to the final call
1840 of L{Context.set_client_ca_list} are used to configure the CA names
1841 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001842 """
1843 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1844 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1845 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1846
1847 cadesc = cacert.get_subject()
1848 sedesc = secert.get_subject()
1849 cldesc = clcert.get_subject()
1850
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001851 def changed_ca(ctx):
1852 ctx.set_client_ca_list([sedesc, cldesc])
1853 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001854 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001855 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001856
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001857
1858 def test_mutated_ca_list(self):
1859 """
1860 If the list passed to L{Context.set_client_ca_list} is mutated
1861 afterwards, this does not affect the list of CA names sent to the
1862 client.
1863 """
1864 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1865 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1866
1867 cadesc = cacert.get_subject()
1868 sedesc = secert.get_subject()
1869
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001870 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001871 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001872 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001873 L.append(sedesc)
1874 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001875 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001876
1877
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001878 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001879 """
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001880 L{Context.add_client_ca} raises L{TypeError} if called with a non-X509
1881 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001882 """
1883 ctx = Context(TLSv1_METHOD)
1884 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001885 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001886 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001887 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001888
1889
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001890 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001891 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001892 A certificate's subject can be added as a CA to be sent to the client
1893 with L{Context.add_client_ca}.
1894 """
1895 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1896 cadesc = cacert.get_subject()
1897 def single_ca(ctx):
1898 ctx.add_client_ca(cacert)
1899 return [cadesc]
1900 self._check_client_ca_list(single_ca)
1901
1902
1903 def test_multiple_add_client_ca(self):
1904 """
1905 Multiple CA names can be sent to the client by calling
1906 L{Context.add_client_ca} with multiple X509 objects.
1907 """
1908 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1909 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1910
1911 cadesc = cacert.get_subject()
1912 sedesc = secert.get_subject()
1913
1914 def multiple_ca(ctx):
1915 ctx.add_client_ca(cacert)
1916 ctx.add_client_ca(secert)
1917 return [cadesc, sedesc]
1918 self._check_client_ca_list(multiple_ca)
1919
1920
1921 def test_set_and_add_client_ca(self):
1922 """
1923 A call to L{Context.set_client_ca_list} followed by a call to
1924 L{Context.add_client_ca} results in using the CA names from the first
1925 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001926 """
1927 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1928 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1929 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1930
1931 cadesc = cacert.get_subject()
1932 sedesc = secert.get_subject()
1933 cldesc = clcert.get_subject()
1934
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001935 def mixed_set_add_ca(ctx):
1936 ctx.set_client_ca_list([cadesc, sedesc])
1937 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001938 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001939 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001940
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001941
1942 def test_set_after_add_client_ca(self):
1943 """
1944 A call to L{Context.set_client_ca_list} after a call to
1945 L{Context.add_client_ca} replaces the CA name specified by the former
1946 call with the names specified by the latter cal.
1947 """
1948 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1949 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1950 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1951
1952 cadesc = cacert.get_subject()
1953 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001954
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001955 def set_replaces_add_ca(ctx):
1956 ctx.add_client_ca(clcert)
1957 ctx.set_client_ca_list([cadesc])
1958 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001959 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001960 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001961
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04001962
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04001963class InfoConstantTests(TestCase):
1964 """
1965 Tests for assorted constants exposed for use in info callbacks.
1966 """
1967 def test_integers(self):
1968 """
1969 All of the info constants are integers.
1970
1971 This is a very weak test. It would be nice to have one that actually
1972 verifies that as certain info events happen, the value passed to the
1973 info callback matches up with the constant exposed by OpenSSL.SSL.
1974 """
1975 for const in [
1976 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
1977 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
1978 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
1979 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
1980 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
1981 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
1982
1983 self.assertTrue(isinstance(const, int))
1984
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02001985
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04001986if __name__ == '__main__':
1987 main()